blob: b67f455ce133fa16a2d3ca104830642e7d566973 [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.
70)
71
Himani Chawla43f95ff2021-06-03 00:24:12 +053072// constants for ethernet frame extended pm collection
73const (
74 ExtendedPmCreateAttempts = 3
75 UnsupportedCounterValue32bit uint64 = 4294967294
76 UnsupportedCounterValue64bit uint64 = 18446744073709551614
Himani Chawla43f95ff2021-06-03 00:24:12 +053077)
78
Girish Gowdra5a7c4922021-01-22 18:33:41 -080079// OpticalPowerGroupMetrics are supported optical pm names
80var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080081 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
82 "transmit_power_dBm": voltha.PmConfig_GAUGE,
83 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080084}
85
86// OpticalPowerGroupMetrics specific constants
87const (
Girish Gowdrae0140f02021-02-02 16:55:09 -080088 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -080089 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
90 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
91)
92
93// UniStatusGroupMetrics are supported UNI status names
94var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -070095 "uni_port_no": voltha.PmConfig_CONTEXT,
96 "me_class_id": voltha.PmConfig_CONTEXT,
97 "entity_id": voltha.PmConfig_CONTEXT,
98 "configuration_ind": voltha.PmConfig_GAUGE,
99 "oper_status": voltha.PmConfig_GAUGE,
100 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800101}
102
103// UniStatusGroupMetrics specific constants
104const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800105 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800106 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
107 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
108)
109
Girish Gowdrae0140f02021-02-02 16:55:09 -0800110// *** Classical L2 PM Counters begin ***
111
112// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
113// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
114var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
115 "class_id": voltha.PmConfig_CONTEXT,
116 "entity_id": voltha.PmConfig_CONTEXT,
117 "interval_end_time": voltha.PmConfig_CONTEXT,
118 "parent_class_id": voltha.PmConfig_CONTEXT,
119 "parent_entity_id": voltha.PmConfig_CONTEXT,
120 "upstream": voltha.PmConfig_CONTEXT,
121
122 "drop_events": voltha.PmConfig_COUNTER,
123 "octets": voltha.PmConfig_COUNTER,
124 "packets": voltha.PmConfig_COUNTER,
125 "broadcast_packets": voltha.PmConfig_COUNTER,
126 "multicast_packets": voltha.PmConfig_COUNTER,
127 "crc_errored_packets": voltha.PmConfig_COUNTER,
128 "undersize_packets": voltha.PmConfig_COUNTER,
129 "oversize_packets": voltha.PmConfig_COUNTER,
130 "64_octets": voltha.PmConfig_COUNTER,
131 "65_to_127_octets": voltha.PmConfig_COUNTER,
132 "128_to_255_octets": voltha.PmConfig_COUNTER,
133 "256_to_511_octets": voltha.PmConfig_COUNTER,
134 "512_to_1023_octets": voltha.PmConfig_COUNTER,
135 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
136}
137
138// EthernetUniHistory are supported ethernet uni history counters fetched from
139// Ethernet Performance Monitoring History Data ME.
140var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
141 "class_id": voltha.PmConfig_CONTEXT,
142 "entity_id": voltha.PmConfig_CONTEXT,
143 "interval_end_time": voltha.PmConfig_CONTEXT,
144
145 "fcs_errors": voltha.PmConfig_COUNTER,
146 "excessive_collision_counter": voltha.PmConfig_COUNTER,
147 "late_collision_counter": voltha.PmConfig_COUNTER,
148 "frames_too_long": voltha.PmConfig_COUNTER,
149 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
150 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
151 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
152 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
153 "sqe_counter": voltha.PmConfig_COUNTER,
154 "deferred_tx_counter": voltha.PmConfig_COUNTER,
155 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
156 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
157 "alignment_error_counter": voltha.PmConfig_COUNTER,
158 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
159}
160
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800161// FecHistory is supported FEC Performance Monitoring History Data related metrics
162var FecHistory = map[string]voltha.PmConfig_PmType{
163 "class_id": voltha.PmConfig_CONTEXT,
164 "entity_id": voltha.PmConfig_CONTEXT,
165 "interval_end_time": voltha.PmConfig_CONTEXT,
166
167 "corrected_bytes": voltha.PmConfig_COUNTER,
168 "corrected_code_words": voltha.PmConfig_COUNTER,
169 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
170 "total_code_words": voltha.PmConfig_COUNTER,
171 "fec_seconds": voltha.PmConfig_COUNTER,
172}
173
174// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
175// related metrics
176var GemPortHistory = map[string]voltha.PmConfig_PmType{
177 "class_id": voltha.PmConfig_CONTEXT,
178 "entity_id": voltha.PmConfig_CONTEXT,
179 "interval_end_time": voltha.PmConfig_CONTEXT,
180
181 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
182 "received_gem_frames": voltha.PmConfig_COUNTER,
183 "received_payload_bytes": voltha.PmConfig_COUNTER,
184 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
185 "encryption_key_errors": voltha.PmConfig_COUNTER,
186}
187
Himani Chawla43f95ff2021-06-03 00:24:12 +0530188var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
189 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
190 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
191 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
192}
193
194var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
195 0x3800: {"drop_events", "octets", "frames"},
196 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
197 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
198 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
199 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
200}
201
Girish Gowdrae0140f02021-02-02 16:55:09 -0800202// Constants specific for L2 PM collection
203const (
204 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
205 SyncTimeRetryInterval = 15 // Unit seconds
206 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800207 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800208 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800209 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
210 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
211 // attribute (1 byte) in L2 PM GET Requests.
Himani Chawla43f95ff2021-06-03 00:24:12 +0530212 MaxL2PMGetPayLoadSize = 24
213 MaxEthernetFrameExtPmPayloadSize = 25
Girish Gowdrae0140f02021-02-02 16:55:09 -0800214)
215
216// EthernetUniHistoryName specific constants
217const (
218 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
219 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
220 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
221)
222
223// EthernetBridgeHistory specific constants
224const (
225 EthernetUniHistoryName = "Ethernet_UNI_History"
226 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
227 EthernetUniHistoryFrequency = L2PmCollectionInterval
228)
229
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800230// FecHistory specific constants
231const (
232 FecHistoryName = "FEC_History"
233 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
234 FecHistoryFrequency = L2PmCollectionInterval
235)
236
237// GemPortHistory specific constants
238const (
239 GemPortHistoryName = "GEM_Port_History"
240 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
241 GemPortHistoryFrequency = L2PmCollectionInterval
242)
243
Holger Hildebrandt60652202021-11-02 11:09:36 +0000244// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
245const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
246
Girish Gowdra0e533642021-03-02 22:02:51 -0800247// KV Store related constants
248const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000249 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530250 cPmAdd = "add"
251 cPmAdded = "added"
252 cPmRemove = "remove"
253 cPmRemoved = "removed"
254 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800255)
256
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800257// Defines the type for generic metric population function
258type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
259
Girish Gowdrae0140f02021-02-02 16:55:09 -0800260// *** Classical L2 PM Counters end ***
261
Girish Gowdra0e533642021-03-02 22:02:51 -0800262type pmMEData struct {
263 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
264 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
265 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
266}
267
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800268type groupMetric struct {
269 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000270 Enabled bool
271 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800272 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000273 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
274 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800275 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800276 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800277}
278
279type standaloneMetric struct {
280 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000281 Enabled bool
282 Frequency uint32 // valid only if FrequencyOverride is enabled.
283 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800284}
285
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000286// OnuMetricsManager - TODO: add comment
287type OnuMetricsManager struct {
288 deviceID string
289 pDeviceHandler cmn.IdeviceHandler
290 pOnuDeviceEntry cmn.IonuDeviceEntry
291 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800292
Himani Chawlaee10b542021-09-20 16:46:40 +0530293 opticalMetricsChan chan me.AttributeValueMap
294 uniStatusMetricsChan chan me.AttributeValueMap
295 l2PmChan chan me.AttributeValueMap
296 extendedPmMeChan chan me.AttributeValueMap
297 syncTimeResponseChan chan bool // true is success, false is fail
298 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
299 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800300
301 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
302 l2PmToDelete []string // list of L2 PMs to delete
303 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800304
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000305 GroupMetricMap map[string]*groupMetric
306 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800307
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000308 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700309 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800310
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000311 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700312 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800313
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000314 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800315
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000316 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800317
318 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530319
320 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530321 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
322 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530323 extPmKvStore *db.Backend
324 onuEthernetFrameExtendedPmLock sync.RWMutex
325 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530326 isEthernetFrameExtendedPmOperationOngoing bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800327}
328
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000329// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800330// The metrics manager module is responsible for configuration and management of individual and group metrics.
331// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
332// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
333// the collection interval configurable.
334// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
335// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000336func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800337
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000338 var metricsManager OnuMetricsManager
339 metricsManager.deviceID = dh.GetDeviceID()
340 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800341 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000342 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800343
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000344 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800345 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
346 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800347 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530348 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800349
350 metricsManager.syncTimeResponseChan = make(chan bool)
351 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530352 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800353
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000354 metricsManager.StopProcessingOmciResponses = make(chan bool)
355 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800356
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000357 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
358 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800359
Himani Chawlac77d5372021-07-12 15:42:26 +0530360 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
361 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530362
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000363 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 -0800364 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800365 }
366
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800367 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800368
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800369 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800370 return nil
371 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800372
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800373 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000374 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800375
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000376 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
377 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800378 if metricsManager.pmKvStore == nil {
379 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000380 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800381 return nil
382 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700383 // restore data from KV store
384 if err := metricsManager.restorePmData(ctx); err != nil {
385 logger.Errorw(ctx, "error restoring pm data", log.Fields{"err": err})
386 // we continue given that it does not effect the actual services for the ONU,
387 // but there may be some negative effect on PM collection (there may be some mismatch in
388 // the actual PM config and what is present on the device).
389 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800390
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000391 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
392 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530393 if metricsManager.extPmKvStore == nil {
394 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000395 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530396 return nil
397 }
398
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000399 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800400 return &metricsManager
401}
402
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000403// InitializeMetricCollectionTime - TODO: add comment
404func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
405 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
406 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
407 mm.OnuMetricsManagerLock.Lock()
408 defer mm.OnuMetricsManagerLock.Unlock()
409 for _, v := range mm.GroupMetricMap {
410 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
411 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800412 }
413 }
414
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000415 for _, v := range mm.StandaloneMetricMap {
416 if v.Enabled {
417 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800418 }
419 }
420 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000421 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
422 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800423 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000424 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800425}
426
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000427// UpdateDefaultFrequency - TODO: add comment
428func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800429 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800430 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800431 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
432 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
433 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000434 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
435 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
436 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
437 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 -0800438 return nil
439}
440
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000441// UpdateGroupFreq - TODO: add comment
442func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 var newGroupFreq uint32
444 found := false
445 groupSliceIdx := 0
446 var group *voltha.PmGroupConfig
447 for groupSliceIdx, group = range pmConfigs.Groups {
448 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800449 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
450 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
451 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
452 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800453 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800454 newGroupFreq = group.GroupFreq
455 found = true
456 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800457 }
458 }
459 // if not found update group freq and next collection interval for the group
460 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000461 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800462 return fmt.Errorf("group-name-not-found-%v", aGroupName)
463 }
464
465 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000466 mm.OnuMetricsManagerLock.Lock()
467 defer mm.OnuMetricsManagerLock.Unlock()
468 for k, v := range mm.GroupMetricMap {
469 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
470 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800471 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000472 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800473 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000474 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800475 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000476 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800477 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800478 }
479 }
480 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000481 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
483 }
484 return nil
485}
486
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000487// UpdateMetricFreq - TODO: add comment
488func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800489 var newMetricFreq uint32
490 found := false
491 metricSliceIdx := 0
492 var metric *voltha.PmConfig
493 for metricSliceIdx, metric = range pmConfigs.Metrics {
494 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800495 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
496 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
497 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
498 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800499 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800500 newMetricFreq = metric.SampleFreq
501 found = true
502 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800503 }
504 }
505 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000506 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800507 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
508 }
509
510 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000511 mm.OnuMetricsManagerLock.Lock()
512 defer mm.OnuMetricsManagerLock.Unlock()
513 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800514 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000515 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800516 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000517 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800518 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000519 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800520 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000521 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800522 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800523 }
524 }
525 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000526 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800527 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
528 }
529 return nil
530}
531
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000532// UpdateGroupSupport - TODO: add comment
533func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 groupSliceIdx := 0
535 var group *voltha.PmGroupConfig
536
537 for groupSliceIdx, group = range pmConfigs.Groups {
538 if group.GroupName == aGroupName {
539 break
540 }
541 }
542 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000543 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800544 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
545 }
546
547 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000548 mm.OnuMetricsManagerLock.Lock()
549 defer mm.OnuMetricsManagerLock.Unlock()
550 for k, v := range mm.GroupMetricMap {
551 if k == aGroupName && v.Enabled != group.Enabled {
552 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
553 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800554 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000555 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800556 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800557 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800558 // 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 -0800559 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
560
561 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
562 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
563 // take further action
564 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800565 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800566 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000567 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
568 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800569 }
570 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000571 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800572 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800573 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800574 // 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 -0800575 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
576
577 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
578 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
579 // take further action
580 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800581 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800582 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800584 }
585 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000586 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800587 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000588 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800589 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000590 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 -0800591 }
592 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800593 }
594 }
595
596 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000597 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800598 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
599 }
600 return nil
601}
602
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000603// UpdateMetricSupport - TODO: add comment
604func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800605 metricSliceIdx := 0
606 var metric *voltha.PmConfig
607
608 for metricSliceIdx, metric = range pmConfigs.Metrics {
609 if metric.Name == aMetricName {
610 break
611 }
612 }
613
614 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000615 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800616 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
617 }
618
619 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000620 mm.OnuMetricsManagerLock.Lock()
621 defer mm.OnuMetricsManagerLock.Unlock()
622 for k, v := range mm.StandaloneMetricMap {
623 if k == aMetricName && v.Enabled != metric.Enabled {
624 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
625 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800626 // 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 +0000627 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
628 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800629 }
630 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000631 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 -0800632 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800633 }
634 }
635 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000636 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800637 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
638 }
639 return nil
640}
641
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000642// CollectAllGroupAndStandaloneMetrics - TODO: add comment
643func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
644 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800645 go mm.collectAllGroupMetrics(ctx)
646 } else {
647 go mm.collectAllStandaloneMetrics(ctx)
648 }
649}
650
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000651func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800652 go func() {
653 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300654 metricInfo, err := mm.collectOpticalMetrics(ctx)
655 if err != nil {
656 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000657 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300658 return
659 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800660 if metricInfo != nil {
661 mm.publishMetrics(ctx, metricInfo)
662 }
663 }()
664
665 go func() {
666 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300667 metricInfo, err := mm.collectUniStatusMetrics(ctx)
668 if err != nil {
669 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000670 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300671 return
672 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800673 if metricInfo != nil {
674 mm.publishMetrics(ctx, metricInfo)
675 }
676 }()
677
678 // Add more here
679}
680
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000681func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800682 // None exists as of now, add when available here
683}
684
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000685// CollectGroupMetric - TODO: add comment
686func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800687 switch groupName {
688 case OpticalPowerGroupMetricName:
689 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300690 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800691 mm.publishMetrics(ctx, mi)
692 }
693 }()
694 case UniStatusGroupMetricName:
695 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300696 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800697 mm.publishMetrics(ctx, mi)
698 }
699 }()
700 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000701 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800702 }
703}
704
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000705// CollectStandaloneMetric - TODO: add comment
706func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800707 switch metricName {
708 // None exist as of now, add when available
709 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000710 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800711 }
712}
713
714// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000715func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
716 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800717
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000718 mm.OnuMetricsManagerLock.RLock()
719 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
720 mm.OnuMetricsManagerLock.RUnlock()
721 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300722 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800723 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000724 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800725
Girish Gowdrae09a6202021-01-12 18:10:59 -0800726 var metricInfoSlice []*voltha.MetricInformation
727 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000728 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
729 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
730 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800731
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800732 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800733 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800734 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800735 Ts: float64(raisedTs),
736 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000737 DeviceId: mm.deviceID,
738 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
739 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800740 }
741
Girish Gowdrae09a6202021-01-12 18:10:59 -0800742 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000743 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800744loop:
745 for _, anigInstID := range anigInstKeys {
746 var meAttributes me.AttributeValueMap
747 opticalMetrics := make(map[string]float32)
748 // Get the ANI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000749 requestedAttributes := me.AttributeValueMap{me.AniG_OpticalSignalLevel: 0, me.AniG_TransmitOpticalLevel: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000750 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300751 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000752 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
753 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300754 return nil, err
755 }
756
757 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800758 select {
759 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000760 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
761 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
762 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 -0800763 // The metrics will be empty in this case
764 break loop
765 }
766 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800767 for k := range OpticalPowerGroupMetrics {
768 switch k {
769 case "ani_g_instance_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000770 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800771 opticalMetrics[k] = float32(val.(uint16))
772 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800773 case "transmit_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000774 if val, ok := meAttributes[me.AniG_TransmitOpticalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000775 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 -0800776 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800777 case "receive_power_dBm":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000778 if val, ok := meAttributes[me.AniG_OpticalSignalLevel]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000779 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 -0800780 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800781 default:
782 // do nothing
783 }
784 }
785 }
786 // create slice of metrics given that there could be more than one ANI-G instance and
787 // optical metrics are collected per ANI-G instance
788 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
789 metricInfoSlice = append(metricInfoSlice, &metricInfo)
790 }
791
ozgecanetsiab36ed572021-04-01 10:38:48 +0300792 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800793}
794
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800795// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800796// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000797func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
798 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
799 mm.OnuMetricsManagerLock.RLock()
800 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
801 mm.OnuMetricsManagerLock.RUnlock()
802 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300803 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800804 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000805 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800806
Girish Gowdrae09a6202021-01-12 18:10:59 -0800807 var metricInfoSlice []*voltha.MetricInformation
808 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000809 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
810 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
811 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800812
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800813 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800814 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700815 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800816 Ts: float64(raisedTs),
817 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000818 DeviceId: mm.deviceID,
819 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
820 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800821 }
822
Girish Gowdrae09a6202021-01-12 18:10:59 -0800823 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000824 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800825loop1:
826 for _, unigInstID := range unigInstKeys {
827 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
828 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
829 unigMetrics := make(map[string]float32)
830 var meAttributes me.AttributeValueMap
831 // Get the UNI-G instance optical power attributes
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000832 requestedAttributes := me.AttributeValueMap{me.UniG_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000833 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300834 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000835 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
836 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300837 return nil, err
838 }
839 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800840 // Wait for metrics or timeout
841 select {
842 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000843 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
844 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
845 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 -0800846 // The metrics could be empty in this case
847 break loop1
848 }
849 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800850 for k := range UniStatusGroupMetrics {
851 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800852 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000853 if val, ok := meAttributes[me.UniG_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800854 unigMetrics[k] = float32(val.(byte))
855 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800856 default:
857 // do nothing
858 }
859 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000860 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800861 entityID := val.(uint16)
862 unigMetrics["entity_id"] = float32(entityID)
863 // 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 +0000864 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
865 if uni.EntityID == entityID {
866 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700867 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800868 }
869 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800870 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700871 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800872
Girish Gowdrae09a6202021-01-12 18:10:59 -0800873 // create slice of metrics given that there could be more than one UNI-G instance
874 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
875 metricInfoSlice = append(metricInfoSlice, &metricInfo)
876 }
877 }
878
879 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000880 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800881loop2:
882 for _, pptpInstID := range pptpInstKeys {
883 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
884 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
885 var meAttributes me.AttributeValueMap
886 pptpMetrics := make(map[string]float32)
887
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000888 requestedAttributes := me.AttributeValueMap{
889 me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd: 0,
890 me.PhysicalPathTerminationPointEthernetUni_OperationalState: 0,
891 me.PhysicalPathTerminationPointEthernetUni_AdministrativeState: 0}
892 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID,
893 pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300894 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000895 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
896 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300897 return nil, err
898 }
899 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800900 // Wait for metrics or timeout
901 select {
902 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000903 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
904 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
905 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 -0800906 // The metrics could be empty in this case
907 break loop2
908 }
909
910 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800911 for k := range UniStatusGroupMetrics {
912 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700913 case "configuration_ind":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000914 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_ConfigurationInd]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800915 pptpMetrics[k] = float32(val.(byte))
916 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800917 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000918 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800919 pptpMetrics[k] = float32(val.(byte))
920 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800921 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000922 if val, ok := meAttributes[me.PhysicalPathTerminationPointEthernetUni_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800923 pptpMetrics[k] = float32(val.(byte))
924 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800925 default:
926 // do nothing
927 }
928 }
929 }
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000930 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800931 entityID := val.(uint16)
932 pptpMetrics["entity_id"] = float32(entityID)
933 // 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 +0000934 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
935 if uni.EntityID == entityID {
936 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700937 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800938 }
939 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800940 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700941 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800942
Girish Gowdrae09a6202021-01-12 18:10:59 -0800943 // create slice of metrics given that there could be more than one PPTP instance and
944 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
945 metricInfoSlice = append(metricInfoSlice, &metricInfo)
946 }
947
948 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000949 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950loop3:
951 for _, veipInstID := range veipInstKeys {
952 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
953 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
954 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800955 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800956
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000957 requestedAttributes := me.AttributeValueMap{me.VirtualEthernetInterfacePoint_OperationalState: 0, me.VirtualEthernetInterfacePoint_AdministrativeState: 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000958 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300959 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000960 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
961 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300962 return nil, err
963 }
964 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800965 // Wait for metrics or timeout
966 select {
967 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000968 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
969 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
970 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 -0800971 // The metrics could be empty in this case
972 break loop3
973 }
974
975 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800976 for k := range UniStatusGroupMetrics {
977 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800978 case "oper_status":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000979 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_OperationalState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800980 veipMetrics[k] = float32(val.(byte))
981 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800982 case "uni_admin_state":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000983 if val, ok := meAttributes[me.VirtualEthernetInterfacePoint_AdministrativeState]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800984 veipMetrics[k] = float32(val.(byte))
985 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800986 default:
987 // do nothing
988 }
989 }
990 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800991
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +0000992 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800993 entityID := val.(uint16)
994 veipMetrics["entity_id"] = float32(entityID)
995 // 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 +0000996 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
997 if uni.EntityID == entityID {
998 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700999 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001000 }
1001 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001002 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001003 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001004
Girish Gowdrae09a6202021-01-12 18:10:59 -08001005 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001006 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001007 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1008 }
1009
ozgecanetsiab36ed572021-04-01 10:38:48 +03001010 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001011}
1012
1013// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001014func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001015 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001016 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001017 ke.SliceData = metricInfo
1018 ke.Type = voltha.KpiEventType_slice
1019 ke.Ts = float64(ts)
1020
Himani Chawlaf9768882021-12-01 00:18:58 +05301021 if err := mm.pDeviceHandler.GetEventProxy().SendKpiEvent(ctx, "STATS_PUBLISH_EVENT", &ke, voltha.EventCategory_EQUIPMENT, voltha.EventSubCategory_ONU, ts); err != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"err": err})
1023 }
1024}
1025
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001026// ProcessOmciMessages - TODO: add comment
1027func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context) {
1028 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 -08001029 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001030 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001031 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001032 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001033 // is stopped - as a result of ONU going down.
1034 mm.flushMetricCollectionChannels(ctx)
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001035 mm.updateOmciProcessingStatus(true)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001036 for {
1037 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001038 case <-mm.StopProcessingOmciResponses: // stop this routine
1039 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 -07001040 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001041 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001042 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001043 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001044 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001045 continue
1046 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001047 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001048
1049 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001050 case cmn.OMCI:
1051 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001052 mm.handleOmciMessage(ctx, msg)
1053 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001054 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001055 }
1056 }
1057 }
1058}
1059
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001060func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1061 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001062 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1063 switch msg.OmciMsg.MessageType {
1064 case omci.GetResponseType:
1065 //TODO: error handling
1066 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001067 case omci.SynchronizeTimeResponseType:
1068 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1069 case omci.CreateResponseType:
1070 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1071 case omci.DeleteResponseType:
1072 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301073 case omci.GetCurrentDataResponseType:
1074 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301075 case omci.SetResponseType:
1076 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001077 default:
1078 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"msgType": msg.OmciMsg.MessageType})
1079
1080 }
1081}
1082
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001083func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1085 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001086 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1087 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001088 }
1089 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1090 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001091 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1092 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001093 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001094 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 -08001095 if msgObj.Result == me.Success {
1096 meAttributes := msgObj.Attributes
1097 switch msgObj.EntityClass {
1098 case me.AniGClassID:
1099 mm.opticalMetricsChan <- meAttributes
1100 return nil
1101 case me.UniGClassID:
1102 mm.uniStatusMetricsChan <- meAttributes
1103 return nil
1104 case me.PhysicalPathTerminationPointEthernetUniClassID:
1105 mm.uniStatusMetricsChan <- meAttributes
1106 return nil
1107 case me.VirtualEthernetInterfacePointClassID:
1108 mm.uniStatusMetricsChan <- meAttributes
1109 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001110 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1111 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001112 me.EthernetPerformanceMonitoringHistoryDataClassID,
1113 me.FecPerformanceMonitoringHistoryDataClassID,
1114 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001115 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301116 return nil
1117 case me.EthernetFrameExtendedPmClassID,
1118 me.EthernetFrameExtendedPm64BitClassID:
1119 mm.extendedPmMeChan <- meAttributes
1120 return nil
1121 default:
1122 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001123 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301124 }
1125 } else {
1126 meAttributes := msgObj.Attributes
1127 switch msgObj.EntityClass {
1128 case me.EthernetFrameExtendedPmClassID,
1129 me.EthernetFrameExtendedPm64BitClassID:
1130 // not all counters may be supported in which case we have seen some ONUs throwing
1131 // AttributeFailure error code, while correctly populating other counters it supports
1132 mm.extendedPmMeChan <- meAttributes
1133 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001134 default:
1135 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001136 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001137 }
1138 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001139 return fmt.Errorf("unhandled-omci-get-response-message")
1140}
1141
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001142func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301143 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1144 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001145 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1146 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301147 }
1148 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1149 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001150 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1151 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301152 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001153 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 +05301154 if msgObj.Result == me.Success {
1155 meAttributes := msgObj.Attributes
1156 switch msgObj.EntityClass {
1157 case me.EthernetFrameExtendedPmClassID,
1158 me.EthernetFrameExtendedPm64BitClassID:
1159 mm.extendedPmMeChan <- meAttributes
1160 return nil
1161 default:
1162 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001163 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301164 }
1165 } else {
1166 meAttributes := msgObj.Attributes
1167 switch msgObj.EntityClass {
1168 case me.EthernetFrameExtendedPmClassID,
1169 me.EthernetFrameExtendedPm64BitClassID:
1170 // not all counters may be supported in which case we have seen some ONUs throwing
1171 // AttributeFailure error code, while correctly populating other counters it supports
1172 mm.extendedPmMeChan <- meAttributes
1173 return nil
1174 default:
1175 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001176 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301177 }
1178 }
1179 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1180}
1181
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001182func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001183 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1184 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001185 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1186 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 -08001187 }
1188 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1189 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001190 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1191 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 -08001192 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001193 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001194 if msgObj.Result == me.Success {
1195 switch msgObj.EntityClass {
1196 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001197 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001198 mm.syncTimeResponseChan <- true
1199 return nil
1200 default:
1201 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001202 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001203 }
1204 }
1205 mm.syncTimeResponseChan <- false
1206 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1207 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001208}
1209
Himani Chawlaee10b542021-09-20 16:46:40 +05301210func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1211 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1212 if msgLayer == nil {
1213 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1214 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1215 }
1216 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1217 if !msgOk {
1218 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1219 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1220 }
1221 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1222 switch msgObj.EntityClass {
1223 case me.EthernetFrameExtendedPmClassID,
1224 me.EthernetFrameExtendedPm64BitClassID:
1225 mm.extendedPMMeResponseChan <- msgObj.Result
1226 return nil
1227 default:
1228 logger.Errorw(ctx, "unhandled omci set response message",
1229 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1230 }
1231 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1232}
1233
Girish Gowdrae09a6202021-01-12 18:10:59 -08001234// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001235func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001236 // flush commMetricsChan
1237 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001238 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001239 logger.Debug(ctx, "flushed common metrics channel")
1240 default:
1241 }
1242
1243 // flush opticalMetricsChan
1244 select {
1245 case <-mm.opticalMetricsChan:
1246 logger.Debug(ctx, "flushed optical metrics channel")
1247 default:
1248 }
1249
1250 // flush uniStatusMetricsChan
1251 select {
1252 case <-mm.uniStatusMetricsChan:
1253 logger.Debug(ctx, "flushed uni status metrics channel")
1254 default:
1255 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001256
1257 // flush syncTimeResponseChan
1258 select {
1259 case <-mm.syncTimeResponseChan:
1260 logger.Debug(ctx, "flushed sync time response channel")
1261 default:
1262 }
1263
1264 // flush l2PmChan
1265 select {
1266 case <-mm.l2PmChan:
1267 logger.Debug(ctx, "flushed L2 PM collection channel")
1268 default:
1269 }
1270
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001271 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001272 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001273 case <-mm.StopTicks:
1274 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001275 default:
1276 }
1277
1278}
1279
1280// ** L2 PM FSM Handlers start **
1281
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001282func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001283
Girish Gowdrae0140f02021-02-02 16:55:09 -08001284 // Loop through all the group metrics
1285 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1286 // list of active L2 PM list then mark it for creation
1287 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1288 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001289 mm.OnuMetricsManagerLock.Lock()
1290 for n, g := range mm.GroupMetricMap {
1291 if g.IsL2PMCounter { // it is a l2 pm counter
1292 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001293 found := false
1294 inner1:
1295 for _, v := range mm.activeL2Pms {
1296 if v == n {
1297 found = true // metric already present in active l2 pm list
1298 break inner1
1299 }
1300 }
1301 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001302 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001303 }
1304 } else { // metric not enabled.
1305 found := false
1306 inner2:
1307 for _, v := range mm.activeL2Pms {
1308 if v == n {
1309 found = true // metric is found in active l2 pm list
1310 break inner2
1311 }
1312 }
1313 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001314 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001315 }
1316 }
1317 }
1318 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001319 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001320 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001321 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001322 go func() {
1323 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001324 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1325 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001326 }
1327 }()
1328}
1329
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001330func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001331 // Sync time with the ONU to establish 15min boundary for PM collection.
1332 if err := mm.syncTime(ctx); err != nil {
1333 go func() {
1334 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1335 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001336 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); 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 // Initiate a tick generation routine every L2PmCollectionInterval
1342 go mm.generateTicks(ctx)
1343
1344 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001345 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1346 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001347 }
1348 }()
1349}
1350
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001351func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001352 // 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 +00001353 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001354 mm.activeL2Pms = nil
1355 mm.l2PmToAdd = nil
1356 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001357 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001358 // If the FSM was stopped, then clear PM data from KV store
1359 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001360 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001361 _ = mm.clearPmGroupData(ctx) // ignore error
1362 }
1363
Girish Gowdrae0140f02021-02-02 16:55:09 -08001364}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001365func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1366 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001367
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001368 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001369 numOfPmToDelete := len(mm.l2PmToDelete)
1370 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001371 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001372
1373 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001374 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 -08001375 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001376 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1377 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001378 }
1379 }()
1380 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001381 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 -08001382 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001383 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1384 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001385 }
1386 }()
1387 }
1388}
1389
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001390func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1391 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001392 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001393 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001394 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1395 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001396 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001397
1398 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001399 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001400
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001401 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1402 mm.OnuMetricsManagerLock.RLock()
1403 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1404 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1405 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001406
Girish Gowdrae0140f02021-02-02 16:55:09 -08001407 switch n {
1408 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001409 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001410 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001411 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1412 metricInfoSlice = append(metricInfoSlice, metricInfo)
1413 }
1414 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1415 metricInfoSlice = append(metricInfoSlice, metricInfo)
1416 }
1417 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001418 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001419 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001420 for _, entityID := range copyOfEntityIDs {
1421 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1422 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001423 }
1424 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001425
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001426 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001427 for _, entityID := range copyOfEntityIDs {
1428 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001429 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001430 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001431 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001432 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001433 for _, entityID := range copyOfEntityIDs {
1434 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001435 metricInfoSlice = append(metricInfoSlice, metricInfo)
1436 }
1437 }
1438
Girish Gowdrae0140f02021-02-02 16:55:09 -08001439 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001440 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001441 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001442 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001443 }
1444 // Does not matter we send success or failure here.
1445 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1446 // we have not exceed max attempts to collect the PM data)
1447 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001448 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1449 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001450 }
1451 }()
1452}
1453
Girish Gowdra0e533642021-03-02 22:02:51 -08001454// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001455func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001456 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001457 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001458 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1459 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001460 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001461
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001462 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001463 for _, n := range copyOfL2PmToAdd {
1464 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001465 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1466 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001467 switch n {
1468 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001469 // 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 +05301470 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001471 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001472 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001473 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001474 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1475 inner1:
1476 // retry L2PmCreateAttempts times to create the instance of PM
1477 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001478 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1479 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001480 if err != nil {
1481 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001482 log.Fields{"device-id": mm.deviceID})
1483 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001484 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001485 go func(p_pmFsm *cmn.AdapterFsm) {
1486 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001487 }(pPMFsm)
1488 }
1489 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001490 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001491 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001492 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1493 atLeastOneSuccess = true
1494 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1495 break inner1
1496 }
1497 }
1498 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1499 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001500 }
1501 }
1502 }
1503 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001504 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1505 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001506 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001507 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001508 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1509 inner2:
1510 // retry L2PmCreateAttempts times to create the instance of PM
1511 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001512 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1513 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001514 if err != nil {
1515 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001516 log.Fields{"device-id": mm.deviceID})
1517 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001518 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001519 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001520 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001521 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1522 atLeastOneSuccess = true
1523 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1524 break inner2
1525 }
1526 }
1527 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1528 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001529 }
1530 }
1531 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001532 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001533 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001534 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001535 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1536 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001537 if err != nil {
1538 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001539 log.Fields{"device-id": mm.deviceID})
1540 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001541 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001542 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001543 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001544 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1545 inner3:
1546 // retry L2PmCreateAttempts times to create the instance of PM
1547 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1548 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1549 atLeastOneSuccess = true
1550 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1551 break inner3
1552 }
1553 }
1554 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1555 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001556 }
1557 }
1558 case GemPortHistoryName:
1559
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001560 mm.OnuMetricsManagerLock.RLock()
1561 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1562 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1563 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001564
1565 if len(copyOfGemPortInstIDsToAdd) == 0 {
1566 // If there are no gemport history MEs to be created, just skip further processing
1567 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1568 // 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 +00001569 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001570 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001571 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001572 continue
1573 }
1574
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001575 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001576 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1577 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001578 if err != nil {
1579 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001580 log.Fields{"device-id": mm.deviceID})
1581 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001582 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001583 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001584 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001585 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1586 inner4:
1587 // retry L2PmCreateAttempts times to create the instance of PM
1588 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1589 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1590 atLeastOneSuccess = true
1591 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1592 break inner4
1593 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001594 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001595 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1596 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1597 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001598 }
1599
Girish Gowdrae0140f02021-02-02 16:55:09 -08001600 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001601 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001602 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001603 // 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
1604 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001605 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001606 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001607 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1608 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001609 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001610 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1611 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001612 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 +00001613 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001614 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001615 // 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 -08001616 // 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 +00001617 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001618 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001619 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001620 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001621
Girish Gowdrae0140f02021-02-02 16:55:09 -08001622 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001623 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001624 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001625 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001626 }
1627 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001628 mm.OnuMetricsManagerLock.RLock()
1629 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1630 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001631 // Does not matter we send success or failure here.
1632 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1633 // we have not exceed max attempts to create the PM ME)
1634 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001635 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1636 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001637 }
1638 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001639 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001640}
1641
Girish Gowdra0e533642021-03-02 22:02:51 -08001642// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001643func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001644 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001645 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001646 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1647 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001648 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001649
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001650 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001651 for _, n := range copyOfL2PmToDelete {
1652 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001653 cnt := 0
1654 atLeastOneDeleteFailure := false
1655
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001656 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1657 mm.OnuMetricsManagerLock.RLock()
1658 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1659 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1660 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001661
1662 if len(copyOfEntityIDs) == 0 {
1663 // 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 +00001664 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001665 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1666 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1667 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 +00001668 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001669 continue
1670 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001671 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001672 switch n {
1673 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001674 // 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 +05301675 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001676 for _, entityID := range copyOfEntityIDs {
1677 inner1:
1678 // retry L2PmDeleteAttempts times to delete the instance of PM
1679 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001680 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1681 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001682 if err != nil {
1683 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001684 log.Fields{"device-id": mm.deviceID})
1685 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001686 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001687 go func(p_pmFsm *cmn.AdapterFsm) {
1688 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001689 }(pPMFsm)
1690 }
1691 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001692 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001693 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001694 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1695 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
1696 atLeastOneDeleteFailure = true
1697 } else {
1698 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1699 break inner1
1700 }
1701 }
1702 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1703 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001704 }
1705 }
1706 }
1707 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001708 for _, entityID := range copyOfEntityIDs {
1709 inner2:
1710 // retry L2PmDeleteAttempts times to delete the instance of PM
1711 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001712 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1713 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001714 if err != nil {
1715 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001716 log.Fields{"device-id": mm.deviceID})
1717 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001718 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001719 go func(p_pmFsm *cmn.AdapterFsm) {
1720 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001721 }(pmFsm)
1722 return err
1723 }
1724 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001725 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001726 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001727 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdra0e533642021-03-02 22:02:51 -08001728 atLeastOneDeleteFailure = true
1729 } else {
1730 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001731 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001732 }
1733 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001734 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1735 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1736 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001737 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001738 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001739 for _, entityID := range copyOfEntityIDs {
1740 inner3:
1741 // retry L2PmDeleteAttempts times to delete the instance of PM
1742 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001743 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1744 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001745 if err != nil {
1746 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001747 log.Fields{"device-id": mm.deviceID})
1748 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001749 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-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 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
1753 atLeastOneDeleteFailure = true
1754 } else {
1755 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1756 break inner3
1757 }
1758 }
1759 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1760 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001761 }
1762 }
1763 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001764 for _, entityID := range copyOfEntityIDs {
1765 inner4:
1766 // retry L2PmDeleteAttempts times to delete the instance of PM
1767 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001768 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1769 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001770 if err != nil {
1771 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001772 log.Fields{"device-id": mm.deviceID})
1773 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001774 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001775 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001776 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001777 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
1778 atLeastOneDeleteFailure = true
1779 } else {
1780 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1781 break inner4
1782 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001783 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001784 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1785 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1786 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001787 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001788 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001789 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001790 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001791 // If we could not completely clean up the PM ME then just give up.
1792 if atLeastOneDeleteFailure {
1793 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001794 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001795 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001796 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001797 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1798 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1799 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001800 mm.GroupMetricMap[n].Enabled = false
1801 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001802 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001803 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001804 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001805 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1806 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001807 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001808 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1809 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001810 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 +00001811 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001812 }
1813 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001814 mm.OnuMetricsManagerLock.RLock()
1815 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1816 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001817 // Does not matter we send success or failure here.
1818 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1819 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001820 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1821 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001822 }
1823 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001824 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001825}
1826
1827// ** L2 PM FSM Handlers end **
1828
1829// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001830func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
1831 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1832 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001833 return err
1834 }
1835
1836 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001837 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1838 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1839 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001840 case syncTimeRes := <-mm.syncTimeResponseChan:
1841 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001842 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001843 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001844 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001845 return nil
1846 }
1847}
1848
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001849func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001850 var mEnt *me.ManagedEntity
1851 var omciErr me.OmciErrors
1852 var classID me.ClassID
1853 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001854 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001855 meParam := me.ParamData{EntityID: entityID}
1856 if upstream {
1857 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001858 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001859 return nil
1860 }
1861 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1862 } else {
1863 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001864 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001865 return nil
1866 }
1867 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1868 }
1869
Girish Gowdrae0140f02021-02-02 16:55:09 -08001870 intervalEndTime := -1
1871 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001872 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1873 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001874 }
1875
1876 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1877 ethPMHistData["class_id"] = float32(classID)
1878 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1879 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1880 ethPMHistData["parent_entity_id"] = float32(entityID)
1881 if upstream {
1882 ethPMHistData["upstream"] = float32(1)
1883 } else {
1884 ethPMHistData["upstream"] = float32(0)
1885 }
1886
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001887 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001888
Girish Gowdrae0140f02021-02-02 16:55:09 -08001889 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001890 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001891 return &metricInfo
1892}
1893
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001894func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001895 var mEnt *me.ManagedEntity
1896 var omciErr me.OmciErrors
1897 var classID me.ClassID
1898 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001899 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001900 meParam := me.ParamData{EntityID: entityID}
1901 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001902 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001903 return nil
1904 }
1905 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
1906
Girish Gowdrae0140f02021-02-02 16:55:09 -08001907 intervalEndTime := -1
1908 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001909 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
1910 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001911 }
1912
1913 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1914 ethUniHistData["class_id"] = float32(classID)
1915 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
1916
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001917 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001918
Girish Gowdrae0140f02021-02-02 16:55:09 -08001919 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001920 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001921 return &metricInfo
1922}
1923
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001924func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001925 var mEnt *me.ManagedEntity
1926 var omciErr me.OmciErrors
1927 var classID me.ClassID
1928 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001929 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001930 meParam := me.ParamData{EntityID: entityID}
1931 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001932 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001933 return nil
1934 }
1935 classID = me.FecPerformanceMonitoringHistoryDataClassID
1936
1937 intervalEndTime := -1
1938 fecHistData := make(map[string]float32)
1939 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
1940 return nil
1941 }
1942
1943 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1944 fecHistData["class_id"] = float32(classID)
1945 fecHistData["interval_end_time"] = float32(intervalEndTime)
1946
1947 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
1948
1949 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001950 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001951 return &metricInfo
1952}
1953
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001954func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001955 var mEnt *me.ManagedEntity
1956 var omciErr me.OmciErrors
1957 var classID me.ClassID
1958 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001959 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001960 meParam := me.ParamData{EntityID: entityID}
1961 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001962 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001963 return nil
1964 }
1965 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
1966
1967 intervalEndTime := -1
1968 gemHistData := make(map[string]float32)
1969 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
1970 return nil
1971 }
1972
1973 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
1974 gemHistData["class_id"] = float32(classID)
1975 gemHistData["interval_end_time"] = float32(intervalEndTime)
1976
1977 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
1978
1979 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001980 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001981 return &metricInfo
1982}
1983
Girish Gowdrae0140f02021-02-02 16:55:09 -08001984// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001985func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08001986 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001987 upstream := false
1988 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
1989 upstream = true
1990 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07001991 // 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 +00001992 requestedAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_IntervalEndTime] = 0
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001993 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001994 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001995 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
1996 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001997 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001998 go func(p_pmFsm *cmn.AdapterFsm) {
1999 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002000 }(pmFsm)
2001 return err
2002 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002003 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002004 }
2005 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002006 select {
2007 case meAttributes = <-mm.l2PmChan:
2008 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002009 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2010 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002011 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002012 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002013 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002014 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002015 }
2016 // 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 -08002017 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002018 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002019 }
2020 }
2021 for k := range EthernetBridgeHistory {
2022 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2023 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2024 if _, ok := ethPMHistData[k]; !ok {
2025 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002026 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002027 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002028 ethPMHistData[k] = float32(val.(uint16))
2029 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002030 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002031 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_DropEvents]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002032 ethPMHistData[k] = float32(val.(uint32))
2033 }
2034 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002035 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002036 ethPMHistData[k] = float32(val.(uint32))
2037 }
2038 case "packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002039 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002040 ethPMHistData[k] = float32(val.(uint32))
2041 }
2042 case "broadcast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002043 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_BroadcastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002044 ethPMHistData[k] = float32(val.(uint32))
2045 }
2046 case "multicast_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002047 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_MulticastPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002048 ethPMHistData[k] = float32(val.(uint32))
2049 }
2050 case "crc_errored_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002051 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_CrcErroredPackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002052 ethPMHistData[k] = float32(val.(uint32))
2053 }
2054 case "undersize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002055 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_UndersizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002056 ethPMHistData[k] = float32(val.(uint32))
2057 }
2058 case "oversize_packets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002059 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_OversizePackets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002060 ethPMHistData[k] = float32(val.(uint32))
2061 }
2062 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002063 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets64Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002064 ethPMHistData[k] = float32(val.(uint32))
2065 }
2066 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002067 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets65To127Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002068 ethPMHistData[k] = float32(val.(uint32))
2069 }
2070 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002071 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets128To255Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002072 ethPMHistData[k] = float32(val.(uint32))
2073 }
2074 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002075 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets256To511Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002076 ethPMHistData[k] = float32(val.(uint32))
2077 }
2078 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002079 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets512To1023Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002080 ethPMHistData[k] = float32(val.(uint32))
2081 }
2082 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002083 if val, ok := meAttributes[me.EthernetFramePerformanceMonitoringHistoryDataUpstream_Packets1024To1518Octets]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002084 ethPMHistData[k] = float32(val.(uint32))
2085 }
2086 default:
2087 // do nothing
2088 }
2089 }
2090 }
2091 return nil
2092}
2093
2094// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002095func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002096 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002097 // 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 +03002098 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2099 requestedAttributes["IntervalEndTime"] = 0
2100 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002101 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002102 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002103 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2104 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2105 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002106 }
2107 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002108 select {
2109 case meAttributes = <-mm.l2PmChan:
2110 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002111 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2112 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002113 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002114 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002115 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002116 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002117 }
2118 // 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 -08002119 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002120 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002121 }
2122 }
2123 for k := range EthernetUniHistory {
2124 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2125 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2126 if _, ok := ethPMUniHistData[k]; !ok {
2127 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002128 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002129 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002130 ethPMUniHistData[k] = float32(val.(uint16))
2131 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002132 case "fcs_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002133 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FcsErrors]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002134 ethPMUniHistData[k] = float32(val.(uint32))
2135 }
2136 case "excessive_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002137 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_ExcessiveCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002138 ethPMUniHistData[k] = float32(val.(uint32))
2139 }
2140 case "late_collision_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002141 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_LateCollisionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002142 ethPMUniHistData[k] = float32(val.(uint32))
2143 }
2144 case "frames_too_long":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002145 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_FramesTooLong]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002146 ethPMUniHistData[k] = float32(val.(uint32))
2147 }
2148 case "buffer_overflows_on_rx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002149 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnReceive]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002150 ethPMUniHistData[k] = float32(val.(uint32))
2151 }
2152 case "buffer_overflows_on_tx":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002153 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_BufferOverflowsOnTransmit]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002154 ethPMUniHistData[k] = float32(val.(uint32))
2155 }
2156 case "single_collision_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002157 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SingleCollisionFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002158 ethPMUniHistData[k] = float32(val.(uint32))
2159 }
2160 case "multiple_collisions_frame_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002161 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_MultipleCollisionsFrameCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002162 ethPMUniHistData[k] = float32(val.(uint32))
2163 }
2164 case "sqe_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002165 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_SqeCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002166 ethPMUniHistData[k] = float32(val.(uint32))
2167 }
2168 case "deferred_tx_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002169 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_DeferredTransmissionCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002170 ethPMUniHistData[k] = float32(val.(uint32))
2171 }
2172 case "internal_mac_tx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002173 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacTransmitErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002174 ethPMUniHistData[k] = float32(val.(uint32))
2175 }
2176 case "carrier_sense_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002177 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_CarrierSenseErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002178 ethPMUniHistData[k] = float32(val.(uint32))
2179 }
2180 case "alignment_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002181 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_AlignmentErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002182 ethPMUniHistData[k] = float32(val.(uint32))
2183 }
2184 case "internal_mac_rx_error_counter":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002185 if val, ok := meAttributes[me.EthernetPerformanceMonitoringHistoryData_InternalMacReceiveErrorCounter]; ok && val != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002186 ethPMUniHistData[k] = float32(val.(uint32))
2187 }
2188 default:
2189 // do nothing
2190 }
2191 }
2192 }
2193 return nil
2194}
2195
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002196// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002197func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002198 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002199 // 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 +00002200 if _, ok := requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2201 requestedAttributes[me.FecPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002202 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002203 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002204 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002205 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2206 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2207 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002208 }
2209 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002210 select {
2211 case meAttributes = <-mm.l2PmChan:
2212 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002213 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2214 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002215 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002216 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002217 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002218 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002219 }
2220 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2221 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002222 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002223 }
2224 }
2225 for k := range FecHistory {
2226 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2227 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2228 if _, ok := fecHistData[k]; !ok {
2229 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002230 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002231 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002232 fecHistData[k] = float32(val.(uint16))
2233 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002234 case "corrected_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002235 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002236 fecHistData[k] = float32(val.(uint32))
2237 }
2238 case "corrected_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002239 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_CorrectedCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002240 fecHistData[k] = float32(val.(uint32))
2241 }
2242 case "uncorrectable_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002243 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_UncorrectableCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002244 fecHistData[k] = float32(val.(uint32))
2245 }
2246 case "total_code_words":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002247 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_TotalCodeWords]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002248 fecHistData[k] = float32(val.(uint32))
2249 }
2250 case "fec_seconds":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002251 if val, ok := meAttributes[me.FecPerformanceMonitoringHistoryData_FecSeconds]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002252 fecHistData[k] = float32(val.(uint16))
2253 }
2254 default:
2255 // do nothing
2256 }
2257 }
2258 }
2259 return nil
2260}
2261
2262// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002263func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002264 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002265 // 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 +00002266 if _, ok := requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime]; !ok {
2267 requestedAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_IntervalEndTime] = 0
ozgecanetsiab36ed572021-04-01 10:38:48 +03002268 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002269 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002270 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002271 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2272 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2273 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002274 }
2275 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002276 select {
2277 case meAttributes = <-mm.l2PmChan:
2278 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002279 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2280 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002281 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002282 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002283 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002284 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002285 }
2286 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2287 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002288 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002289 }
2290 }
2291 for k := range GemPortHistory {
2292 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2293 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2294 if _, ok := gemPortHistData[k]; !ok {
2295 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002296 case "entity_id":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002297 if val, ok := meAttributes[me.ManagedEntityID]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08002298 gemPortHistData[k] = float32(val.(uint16))
2299 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002300 case "transmitted_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002301 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002302 gemPortHistData[k] = float32(val.(uint32))
2303 }
2304 case "received_gem_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002305 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedGemFrames]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002306 gemPortHistData[k] = float32(val.(uint32))
2307 }
2308 case "received_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002309 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_ReceivedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002310 gemPortHistData[k] = float32(val.(uint64))
2311 }
2312 case "transmitted_payload_bytes":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002313 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_TransmittedPayloadBytes]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002314 gemPortHistData[k] = float32(val.(uint64))
2315 }
2316 case "encryption_key_errors":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00002317 if val, ok := meAttributes[me.GemPortNetworkCtpPerformanceMonitoringHistoryData_EncryptionKeyErrors]; ok && val != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002318 gemPortHistData[k] = float32(val.(uint32))
2319 }
2320 default:
2321 // do nothing
2322 }
2323 }
2324 }
2325 return nil
2326}
2327
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002328func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002329 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2330 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002331 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2332 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 -08002333 }
2334 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2335 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002336 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2337 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 -08002338 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002339 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002340 switch msgObj.EntityClass {
2341 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2342 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002343 me.EthernetPerformanceMonitoringHistoryDataClassID,
2344 me.FecPerformanceMonitoringHistoryDataClassID,
2345 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002346 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2347 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2348 mm.l2PmCreateOrDeleteResponseChan <- true
2349 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002350 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002351 mm.l2PmCreateOrDeleteResponseChan <- false
2352 }
2353 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302354 case me.EthernetFrameExtendedPmClassID,
2355 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302356 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302357 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002358 default:
2359 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002360 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002361 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002362 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002363}
2364
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002365func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002366 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2367 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002368 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2369 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 -08002370 }
2371 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2372 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002373 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2374 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 -08002375 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002376 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002377 switch msgObj.EntityClass {
2378 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2379 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002380 me.EthernetPerformanceMonitoringHistoryDataClassID,
2381 me.FecPerformanceMonitoringHistoryDataClassID,
2382 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002383 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2384 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2385 mm.l2PmCreateOrDeleteResponseChan <- true
2386 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002387 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002388 mm.l2PmCreateOrDeleteResponseChan <- false
2389 }
2390 return nil
2391 default:
2392 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002393 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002394 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002395 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002396}
2397
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002398func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002399 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002400 for {
2401 select {
2402 case <-time.After(L2PmCollectionInterval * time.Second):
2403 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002404 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2405 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002406 }
2407 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002408 case <-mm.StopTicks:
2409 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002410 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002411 return
2412 }
2413 }
2414}
2415
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002416func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002417 // Publish metrics if it is valid
2418 if metricInfoSlice != nil {
2419 mm.publishMetrics(ctx, metricInfoSlice)
2420 } else {
2421 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2422 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002423 mm.OnuMetricsManagerLock.Lock()
2424 mm.GroupMetricMap[metricName].collectAttempts++
2425 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002426 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2427 }
2428 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002429 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2430 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002431 }
2432}
2433
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002434func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002435 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2436 var grpFunc groupMetricPopulateFunc
2437 switch classID {
2438 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2439 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2440 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2441 grpFunc = mm.populateEthernetUniHistoryMetrics
2442 case me.FecPerformanceMonitoringHistoryDataClassID:
2443 grpFunc = mm.populateFecHistoryMetrics
2444 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2445 grpFunc = mm.populateGemPortMetrics
2446 default:
2447 return fmt.Errorf("unknown-classid-%v", classID)
2448 }
2449
2450 size := 0
2451 requestedAttributes := make(me.AttributeValueMap)
2452 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002453 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2454 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2455 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2456 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2457 continue
2458 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002459 if (v.Size + size) <= MaxL2PMGetPayLoadSize {
2460 requestedAttributes[v.Name] = v.DefValue
2461 size = v.Size + size
2462 } else { // We exceeded the allow omci get size
2463 // Let's collect the attributes via get now and collect remaining in the next iteration
2464 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2465 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002466 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002467 return err
2468 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002469 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002470 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2471 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002472 }
2473 }
2474 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002475 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2476 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002477 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002478 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002479 }
2480 return nil
2481}
2482
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002483func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002484 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002485 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2486 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2487 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002488
2489 raisedTs := time.Now().Unix()
2490 mmd := voltha.MetricMetaData{
2491 Title: title,
2492 Ts: float64(raisedTs),
2493 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002494 DeviceId: mm.deviceID,
2495 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2496 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002497 }
2498
2499 // create slice of metrics given that there could be more than one VEIP instance
2500 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2501 return metricInfo
2502}
2503
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002504func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002505 valid := false
2506 if *intervalEndTime == -1 { // first time
2507 // Update the interval end time
2508 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2509 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2510 valid = true
2511 }
2512 } else {
2513 var currIntervalEndTime int
2514 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2515 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2516 }
2517 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2518 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002519 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002520 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2521 } else {
2522 valid = true
2523 }
2524 }
2525 return valid
2526}
2527
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002528func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002529 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
2530 select {
2531 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002532 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002533 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002534 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002535 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002536 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002537 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002538 }
2539 return false
2540}
2541
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002542func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002543 var pmConfigSlice []*voltha.PmConfig
2544 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002545 pmConfigSlice = append(pmConfigSlice,
2546 &voltha.PmConfig{
2547 Name: k,
2548 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002550 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002551 }
2552 groupMetric := voltha.PmGroupConfig{
2553 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002554 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002555 GroupFreq: grpFreq,
2556 Metrics: pmConfigSlice,
2557 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002558 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002559
2560}
2561
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002562func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2563 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2564 if mm.PAdaptFsm == nil {
2565 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2566 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002567 return fmt.Errorf("nil-adapter-fsm")
2568 }
2569 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002570 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2571 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002572 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002573 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2574 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2575 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2576 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2577 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2578 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2579 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2580 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2581 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002582 },
2583 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002584 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2585 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2586 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2587 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2588 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2589 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2590 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2591 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002592 },
2593 )
2594 return nil
2595}
2596
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002597func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2598 mm.pDeviceHandler.InitPmConfigs()
2599 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2600 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2601 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2602 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002603
2604 // Populate group metrics.
2605 // Lets populate irrespective of GroupMetricEnabled is true or not.
2606 // The group metrics collection will decided on this flag later
2607
2608 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2609 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2610
2611 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2612 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2613
2614 // classical l2 pm counter start
2615
2616 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2617 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2618
2619 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2620 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2621
2622 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2623 FecHistoryEnabled, FecHistoryFrequency)
2624
2625 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2626 GemPortHistoryEnabled, GemPortHistoryFrequency)
2627
2628 // classical l2 pm counter end
2629
2630 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2631}
2632
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002633func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002634 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002635 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2636 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002637 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002638 Enabled: g.Enabled,
2639 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002640 }
2641 switch g.GroupName {
2642 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002643 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002644 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002646 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002647 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2648 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002649 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002650 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2651 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002652 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002653 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2654 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002655 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002656 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2657 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002658 default:
2659 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"groupName": g.GroupName})
2660 }
2661 }
2662
2663 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002664 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2665 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002666 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002667 Enabled: m.Enabled,
2668 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002669 }
2670 switch m.Name {
2671 // None exist as of now. Add when available.
2672 default:
2673 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"metricName": m.Name})
2674 }
2675 }
2676}
2677
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002678// AddGemPortForPerfMonitoring - TODO: add comment
2679func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2680 mm.OnuMetricsManagerLock.Lock()
2681 defer mm.OnuMetricsManagerLock.Unlock()
2682 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002683 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002684 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002685 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002686 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002687
2688 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2689 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2690 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2691 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2692 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002693
2694 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002695 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2696 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002697 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002698 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002699 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002700 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002701 }
2702 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002703}
2704
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002705// RemoveGemPortForPerfMonitoring - TODO: add comment
2706func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2707 mm.OnuMetricsManagerLock.Lock()
2708 defer mm.OnuMetricsManagerLock.Unlock()
2709 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2710 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002711 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002712 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002713
2714 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2715 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2716 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2717 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2718 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002719
2720 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002721 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2722 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002723 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002724 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002725 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002726 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002727 }
2728 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002729}
2730
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002731func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2732 if mm.pDeviceHandler.GetOnuTP() != nil {
2733 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002734 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002735 for _, v := range gemPortInstIDs {
2736 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002737 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002738 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002739 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002740 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002741 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002742 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002743 }
2744}
2745
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002746func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2747 if mm.pDeviceHandler.GetOnuTP() != nil {
2748 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002749 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002750 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002751 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002752 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002753 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002754 }
2755 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002756 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002757 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002758}
2759
2760// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002761func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2762 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002763 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002764 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2765 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002766 }
2767 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002768 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002769 group.pmMEData = &pmMEData{}
2770 Value, err := mm.pmKvStore.Get(ctx, groupName)
2771 if err == nil {
2772 if Value != nil {
2773 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002774 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002775 tmpBytes, _ := kvstore.ToByte(Value.Value)
2776
2777 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002778 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2779 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 -08002780 continue
2781 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002782 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002783 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002784 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002785 continue
2786 }
2787 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2789 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 -08002790 continue
2791 }
2792 }
2793 if len(errorsList) > 0 {
2794 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2795 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002796 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002797 return nil
2798}
2799
2800// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2801// the data must be available in cache.
2802// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002803func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2804 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002805 return grp.pmMEData, nil
2806 }
2807 // Data not in cache, try to fetch from kv store.
2808 data := &pmMEData{}
2809 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002810 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2811 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002812 }
2813 Value, err := mm.pmKvStore.Get(ctx, groupName)
2814 if err == nil {
2815 if Value != nil {
2816 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002817 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002818 tmpBytes, _ := kvstore.ToByte(Value.Value)
2819
2820 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002821 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002822 return data, err
2823 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002824 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002825 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002826 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002827 return data, err
2828 }
2829 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002830 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002831 return data, err
2832 }
2833
2834 return data, nil
2835}
2836
2837// 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 +00002838func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2839 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2840 mm.OnuMetricsManagerLock.Lock()
2841 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002842
2843 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002844 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2845 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002846 }
2847
2848 pmMEData, err := mm.getPmData(ctx, groupName)
2849 if err != nil || pmMEData == nil {
2850 // error already logged in called function.
2851 return err
2852 }
2853 switch pmAction {
2854 case cPmAdd:
2855 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2856 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2857 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2858 case cPmAdded:
2859 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2860 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2861 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2862 case cPmRemove:
2863 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2864 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2865 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2866 case cPmRemoved:
2867 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2868 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2869 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2870 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002871 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2872 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 -08002873 }
2874 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002875 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002876
2877 Value, err := json.Marshal(*pmMEData)
2878 if err != nil {
2879 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
2880 return err
2881 }
2882 // Update back to kv store
2883 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
2884 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
2885 return err
2886 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002887 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002888
2889 return nil
2890}
2891
2892// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002893func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2894 mm.OnuMetricsManagerLock.Lock()
2895 defer mm.OnuMetricsManagerLock.Unlock()
2896 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002897 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 fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002900 }
2901
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002902 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002903 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002904 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002905 // do not abort this procedure. continue to delete next group.
2906 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002907 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002908 }
2909 }
2910
2911 return nil
2912}
2913
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002914// ClearAllPmData clears all PM data associated with the device from KV store
2915func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
2916 mm.OnuMetricsManagerLock.Lock()
2917 defer mm.OnuMetricsManagerLock.Unlock()
2918 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002919 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002920 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2921 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002922 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002923 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002924 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002925 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002926 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002927 value = err
2928 // do not abort this procedure - continue to delete next group.
2929 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002930 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002931 }
Girish Gowdra0e533642021-03-02 22:02:51 -08002932 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002933 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002934 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002935 }
2936 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002937}
2938
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002939func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
2940 mm.OnuMetricsManagerLock.Lock()
2941 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002942 mm.omciProcessingActive = status
2943}
2944
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002945// updateTickGenerationStatus - TODO: add comment
2946func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
2947 mm.OnuMetricsManagerLock.Lock()
2948 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002949 mm.tickGenerationActive = status
2950}
2951
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002952// GetOmciProcessingStatus - TODO: add comment
2953func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
2954 mm.OnuMetricsManagerLock.RLock()
2955 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002956 return mm.omciProcessingActive
2957}
2958
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002959// GetTickGenerationStatus - TODO: add comment
2960func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
2961 mm.OnuMetricsManagerLock.RLock()
2962 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002963 return mm.tickGenerationActive
2964}
2965
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002966func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002967 for _, ele := range slice {
2968 if ele == n {
2969 return slice
2970 }
2971 }
2972 return append(slice, n)
2973}
2974
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002975func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002976 for i, ele := range slice {
2977 if ele == n {
2978 return append(slice[:i], slice[i+1:]...)
2979 }
2980 }
2981 return slice
2982}
2983
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002984func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002985 for _, ele := range slice {
2986 if ele == n {
2987 return slice
2988 }
2989 }
2990 return append(slice, n)
2991}
2992
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002993func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002994 for i, ele := range slice {
2995 if ele == n {
2996 return append(slice[:i], slice[i+1:]...)
2997 }
2998 }
2999 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003000}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303001
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003002func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303003 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3004 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003005 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3006 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3007 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303008 Value, err := mm.extPmKvStore.Get(ctx, key)
3009 if err == nil {
3010 if Value != nil {
3011 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003012 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303013 tmpBytes, _ := kvstore.ToByte(Value.Value)
3014
3015 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003016 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303017 return false, err
3018 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003019 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303020 // We have found the data from db, no need to get through omci get message.
3021 mm.supportedEthernetFrameExtendedPMClass = data
3022 return true, nil
3023 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003024 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303025 return false, nil
3026 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003027 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303028 return false, err
3029}
3030
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003031func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303032 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
3033 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303034 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303035 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003036 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303037 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3038 if resp == me.Success || resp == me.InstanceExists {
3039 return true, nil
3040 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3041 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3042 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3043 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003044 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 +05303045 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3046 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003047 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303048 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003049 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303050 }
3051 return false, fmt.Errorf("timeout-while-waiting-for-response")
3052}
3053
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303055 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303056 // 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 +05303057 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003058 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303059 var entityID uint16
3060 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303062 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003063 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303064 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303065 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303066 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303067 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303068
3069 inner1:
3070 // retry ExtendedPmCreateAttempts times to create the instance of PM
3071 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003072 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3073 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3074 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303075 if err != nil {
3076 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003077 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303078 return false, err
3079 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303080 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3081 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303082 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303083 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303084 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303085 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303086 }
3087 break inner1
3088 } else if err != nil {
3089 if !supported {
3090 // Need to return immediately
3091 return false, err
3092 }
3093 //In case of failure, go for a retry
3094 }
3095 }
3096 if cnt == ExtendedPmCreateAttempts {
3097 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3098 return true, fmt.Errorf("unable-to-create-me")
3099 }
3100 }
3101 }
3102 return true, nil
3103}
3104
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003105func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3106 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3107 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3108 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303109 // check if we get the supported type me for ethernet frame extended pm class id
3110 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3111 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3112 }
3113 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3114 if err != nil {
3115 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"err": err})
3116 }
3117 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
3118 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"err": err})
3119 }
3120}
3121
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003122func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303123 mm.onuEthernetFrameExtendedPmLock.Lock()
3124 mm.isDeviceReadyToCollectExtendedPmStats = true
3125 mm.onuEthernetFrameExtendedPmLock.Unlock()
3126}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003127
Himani Chawlaee10b542021-09-20 16:46:40 +05303128// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003129func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303130 //get the type of extended frame pm me supported by onu first
3131 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3132 if err != nil {
3133 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3134 return
3135 }
3136 if exist {
3137 // we have the me type, go ahead with the me type supported.
3138 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003139 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303140 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3141 return
3142 }
3143 mm.setAllExtPmMeCreatedFlag()
3144 return
3145 }
3146 // First try with 64 bit me
3147 // we have the me type, go ahead with the me type supported.
3148 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3149 if err != nil && !supported64Bit {
3150 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003151 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303152 "supported": supported64Bit})
3153 // Then Try with 32 bit type
3154 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003155 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303156 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3157 } else if supported32Bit {
3158 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3159 mm.putExtPmMeKvStore(ctx)
3160 mm.setAllExtPmMeCreatedFlag()
3161 }
3162 } else if err == nil && supported64Bit {
3163 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3164 mm.putExtPmMeKvStore(ctx)
3165 mm.setAllExtPmMeCreatedFlag()
3166 }
3167}
3168
Himani Chawlaee10b542021-09-20 16:46:40 +05303169func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3170 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3171 uniPortEntityID := entityID
3172 if upstream {
3173 uniPortEntityID = entityID - 0x100
3174 }
3175 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3176 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3177 mm.pDeviceHandler.GetOmciTimeout(), true,
3178 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3179 if err != nil {
3180 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3181 log.Fields{"device-id": mm.deviceID})
3182 return extension.GetValueResponse_INTERNAL_ERROR, err
3183 }
3184
3185 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3186 return extension.GetValueResponse_REASON_UNDEFINED, nil
3187 }
3188 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3189}
3190
3191func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3192 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
3193 select {
3194 case resp := <-mm.extendedPMMeResponseChan:
3195 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3196 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3197 if resp == me.Success {
3198 return true
3199 }
3200 return false
3201 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3202 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3203 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3204 }
3205 return false
3206}
3207
3208func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3209 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3210 className := "EthernetFrameExtendedPm64Bit"
3211 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3212 className = "EthernetFrameExtendedPm"
3213 }
3214 // Reset the counters if option is specified
3215 for entityID := range upstreamEntityMap {
3216 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3217 true)
3218 if err != nil {
3219 return errReason, err
3220 }
3221 }
3222
3223 for entityID := range downstreamEntityMap {
3224 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3225 true)
3226 if err != nil {
3227 return errReason, err
3228 }
3229 }
3230 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3231 // device itself.
3232 // Unset the reset bit if option is specified
3233 for entityID := range upstreamEntityMap {
3234 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3235 false)
3236 if err != nil {
3237 return errReason, err
3238 }
3239 }
3240
3241 for entityID := range downstreamEntityMap {
3242 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3243 false)
3244 if err != nil {
3245 return errReason, err
3246 }
3247 }
3248 return extension.GetValueResponse_REASON_UNDEFINED, nil
3249}
3250
3251func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3252 mm.onuEthernetFrameExtendedPmLock.Lock()
3253 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3254 mm.isEthernetFrameExtendedPmOperationOngoing = val
3255}
3256
3257func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3258 mm.onuEthernetFrameExtendedPmLock.Lock()
3259 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3260 return mm.isEthernetFrameExtendedPmOperationOngoing
3261}
3262
3263// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3264func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3265 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3266 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3267 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303268 return &extension.SingleGetValueResponse{
3269 Response: &extension.GetValueResponse{
3270 Status: extension.GetValueResponse_ERROR,
3271 ErrReason: reason,
3272 },
3273 }
3274 }
3275 mm.onuEthernetFrameExtendedPmLock.RLock()
3276 if !mm.isDeviceReadyToCollectExtendedPmStats {
3277 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303278 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303279 }
3280 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303281
3282 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3283 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3284 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3285 }
3286 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3287 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3288
3289 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3290 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3291 if onuInfo.IsUniIndex != nil {
3292 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3293 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3294 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3295 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3296 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3297 break
3298 }
3299 }
3300 if len(downstreamEntityMap) == 0 {
3301 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3302 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3303 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3304 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3305 }
3306 } else {
3307 // make a copy of all downstream and upstream maps in the local ones
3308 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3309 upstreamEntityMap[entityID] = meEnt
3310 }
3311 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3312 downstreamEntityMap[entityID] = meEnt
3313 }
3314 }
3315 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3316 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3317 // Reset the metrics first for all required me's
3318 if onuInfo.Reset_ {
3319 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3320 if err != nil {
3321 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3322 log.Fields{"device-id": mm.deviceID})
3323 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3324 }
3325 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303326 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3327 var pmUpstream extension.OmciEthernetFrameExtendedPm
3328 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303329 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3330 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3331 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3332 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303333 if !onuInfo.Reset_ {
3334 for entityID, meEnt := range upstreamEntityMap {
3335 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3336 var receivedMask uint16
3337 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3338 if receivedMask == 0 {
3339 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303340 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3341 // It might be possible that still some downstream pms are supported and hence we need to continue
3342 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3343 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303344 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303345 // Aggregate the result for upstream
3346 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3347 } else {
3348 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303349 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303350 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303351
Himani Chawlaee10b542021-09-20 16:46:40 +05303352 for entityID, meEnt := range downstreamEntityMap {
3353 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3354 var receivedMask uint16
3355 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303356 if receivedMask == 0 {
3357 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3358 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3359 // Stop collecting downstream counters for other ME's.
3360 break
3361 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303362 // Aggregate the result for downstream
3363 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3364 } else {
3365 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3366 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303367 }
3368 }
3369 singleValResp := extension.SingleGetValueResponse{
3370 Response: &extension.GetValueResponse{
3371 Status: extension.GetValueResponse_OK,
3372 Response: &extension.GetValueResponse_OnuCounters{
3373 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303374 Upstream: &pmUpstream,
3375 Downstream: &pmDownstream,
3376 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303377 },
3378 },
3379 },
3380 }
3381 return &singleValResp
3382}
3383
Himani Chawlaee10b542021-09-20 16:46:40 +05303384func (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 +05303385 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003386 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 +05303387
3388 classID = mm.supportedEthernetFrameExtendedPMClass
3389 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3390 if classID == me.EthernetFrameExtendedPmClassID {
3391 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3392 }
3393 ethPMData := make(map[string]uint64)
3394 var sumReceivedMask uint16
3395 for mask := range attributeMaskList {
3396 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3397 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003398 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303399 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303400 }
3401 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3402 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3403 //populate all counters as failure and return
3404 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3405 break
3406 }
3407 }
3408 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303409 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303410}
3411
3412// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003413func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303414 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3415 var meAttributes me.AttributeValueMap
3416 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003417 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303418 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003419 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303420 return extension.GetValueResponse_INTERNAL_ERROR, err
3421 }
3422 select {
3423 case meAttributes = <-mm.extendedPmMeChan:
3424 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003425 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3426 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303427 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003428 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303429 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3430 }
3431 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3432 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3433 *sumReceivedMask += mask
3434 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3435 } else {
3436 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3437 *sumReceivedMask += mask
3438 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3439 }
3440
3441 return extension.GetValueResponse_REASON_UNDEFINED, nil
3442}
3443
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003444func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303445 sourceMap := maskToEthernetFrameExtendedPM64Bit
3446 errorCounterValue := UnsupportedCounterValue64bit
3447 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3448 sourceMap = maskToEthernetFrameExtendedPM32Bit
3449 errorCounterValue = UnsupportedCounterValue32bit
3450 }
3451 for _, value := range sourceMap {
3452 for _, k := range value {
3453 if _, ok := ethFrameExtPMData[k]; !ok {
3454 ethFrameExtPMData[k] = errorCounterValue
3455 }
3456 }
3457 }
3458}
3459
3460// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003461func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303462 receivedMask := uint16(0)
3463 switch requestedAttributesMask {
3464 case 0x3F00:
3465 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3466 if _, ok := ethFrameExtPMData[k]; !ok {
3467 switch k {
3468 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003469 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303470 ethFrameExtPMData[k] = uint64(val.(uint32))
3471 receivedMask |= 0x2000
3472 } else if !ok {
3473 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3474 }
3475 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003476 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303477 ethFrameExtPMData[k] = uint64(val.(uint32))
3478 receivedMask |= 0x1000
3479 } else if !ok {
3480 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3481 }
3482 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003483 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303484 ethFrameExtPMData[k] = uint64(val.(uint32))
3485 receivedMask |= 0x800
3486 } else if !ok {
3487 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3488 }
3489 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003490 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303491 ethFrameExtPMData[k] = uint64(val.(uint32))
3492 receivedMask |= 0x400
3493 } else if !ok {
3494 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3495 }
3496 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003497 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303498 ethFrameExtPMData[k] = uint64(val.(uint32))
3499 receivedMask |= 0x200
3500 } else if !ok {
3501 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3502 }
3503 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003504 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303505 ethFrameExtPMData[k] = uint64(val.(uint32))
3506 receivedMask |= 0x100
3507 } else if !ok {
3508 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3509 }
3510 default:
3511 //do nothing
3512 }
3513 }
3514 }
3515 case 0x00FC:
3516 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3517 if _, ok := ethFrameExtPMData[k]; !ok {
3518 switch k {
3519 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003520 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303521 ethFrameExtPMData[k] = uint64(val.(uint32))
3522 receivedMask |= 0x80
3523 } else if !ok {
3524 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3525 }
3526 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003527 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303528 ethFrameExtPMData[k] = uint64(val.(uint32))
3529 receivedMask |= 0x40
3530 } else if !ok {
3531 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3532 }
3533 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003534 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303535 ethFrameExtPMData[k] = uint64(val.(uint32))
3536 receivedMask |= 0x20
3537 } else if !ok {
3538 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3539 }
3540 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003541 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303542 ethFrameExtPMData[k] = uint64(val.(uint32))
3543 receivedMask |= 0x10
3544 } else if !ok {
3545 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3546 }
3547 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003548 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303549 ethFrameExtPMData[k] = uint64(val.(uint32))
3550 receivedMask |= 0x8
3551 } else if !ok {
3552 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3553 }
3554 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003555 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303556 ethFrameExtPMData[k] = uint64(val.(uint32))
3557 receivedMask |= 0x4
3558 } else if !ok {
3559 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3560 }
3561 default:
3562 //do nothing
3563 }
3564 }
3565 }
3566 case 0x0003:
3567 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3568 if _, ok := ethFrameExtPMData[k]; !ok {
3569 switch k {
3570 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003571 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303572 ethFrameExtPMData[k] = uint64(val.(uint32))
3573 receivedMask |= 0x2
3574 } else if !ok {
3575 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3576 }
3577 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003578 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303579 ethFrameExtPMData[k] = uint64(val.(uint32))
3580 receivedMask |= 0x1
3581 } else if !ok {
3582 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3583 }
3584 default:
3585 //do nothing
3586 }
3587 }
3588 }
3589 default:
3590 //do nothing
3591 }
3592 return receivedMask
3593}
3594
3595// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003596func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303597 receivedMask := uint16(0)
3598 switch requestedAttributesMask {
3599 case 0x3800:
3600 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3601 if _, ok := ethFrameExtPMData[k]; !ok {
3602 switch k {
3603 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003604 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303605 ethFrameExtPMData[k] = val.(uint64)
3606 receivedMask |= 0x2000
3607 } else if !ok {
3608 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3609 }
3610 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003611 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303612 ethFrameExtPMData[k] = val.(uint64)
3613 receivedMask |= 0x1000
3614 } else if !ok {
3615 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3616 }
3617 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003618 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303619 ethFrameExtPMData[k] = val.(uint64)
3620 receivedMask |= 0x800
3621 } else if !ok {
3622 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3623 }
3624 }
3625 }
3626 }
3627 case 0x0700:
3628 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3629 if _, ok := ethFrameExtPMData[k]; !ok {
3630 switch k {
3631 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003632 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303633 ethFrameExtPMData[k] = val.(uint64)
3634 receivedMask |= 0x400
3635 } else if !ok {
3636 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3637 }
3638 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003639 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303640 ethFrameExtPMData[k] = val.(uint64)
3641 receivedMask |= 0x200
3642 } else if !ok {
3643 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3644 }
3645 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003646 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303647 ethFrameExtPMData[k] = val.(uint64)
3648 receivedMask |= 0x100
3649 } else if !ok {
3650 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3651 }
3652 }
3653 }
3654 }
3655 case 0x00E0:
3656 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3657 if _, ok := ethFrameExtPMData[k]; !ok {
3658 switch k {
3659 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003660 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303661 ethFrameExtPMData[k] = val.(uint64)
3662 receivedMask |= 0x80
3663 } else if !ok {
3664 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3665 }
3666 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003667 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303668 ethFrameExtPMData[k] = val.(uint64)
3669 receivedMask |= 0x40
3670 } else if !ok {
3671 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3672 }
3673 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003674 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303675 ethFrameExtPMData[k] = val.(uint64)
3676 receivedMask |= 0x20
3677 } else if !ok {
3678 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3679 }
3680 }
3681 }
3682 }
3683 case 0x001C:
3684 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3685 if _, ok := ethFrameExtPMData[k]; !ok {
3686 switch k {
3687 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003688 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303689 ethFrameExtPMData[k] = val.(uint64)
3690 receivedMask |= 0x10
3691 } else if !ok {
3692 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3693 }
3694 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003695 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303696 ethFrameExtPMData[k] = val.(uint64)
3697 receivedMask |= 0x8
3698 } else if !ok {
3699 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3700 }
3701 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003702 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303703 ethFrameExtPMData[k] = val.(uint64)
3704 receivedMask |= 0x4
3705 } else if !ok {
3706 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3707 }
3708 default:
3709 //do nothing
3710 }
3711 }
3712 }
3713 case 0x0003:
3714 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3715 if _, ok := ethFrameExtPMData[k]; !ok {
3716 switch k {
3717 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003718 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303719 ethFrameExtPMData[k] = val.(uint64)
3720 receivedMask |= 0x2
3721 } else if !ok {
3722 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3723 }
3724 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003725 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303726 ethFrameExtPMData[k] = val.(uint64)
3727 receivedMask |= 0x1
3728 } else if !ok {
3729 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3730 }
3731 default:
3732 //do nothing
3733 }
3734 }
3735 }
3736 }
3737 return receivedMask
3738}
3739
Himani Chawlaee10b542021-09-20 16:46:40 +05303740func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3741 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303742 errorCounterValue := UnsupportedCounterValue64bit
3743 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3744 errorCounterValue = UnsupportedCounterValue32bit
3745 }
3746 var pmDataOut extension.OmciEthernetFrameExtendedPm
3747 if aggregate {
3748 if pmData.DropEvents != errorCounterValue {
3749 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3750 } else {
3751 pmDataOut.DropEvents = pmData.DropEvents
3752 }
3753 if pmData.Octets != errorCounterValue {
3754 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3755 } else {
3756 pmDataOut.Octets = pmData.Octets
3757 }
3758 if pmData.Frames != errorCounterValue {
3759 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3760 } else {
3761 pmDataOut.Frames = pmData.Frames
3762 }
3763 if pmData.BroadcastFrames != errorCounterValue {
3764 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3765 } else {
3766 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3767 }
3768 if pmData.MulticastFrames != errorCounterValue {
3769 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3770 } else {
3771 pmDataOut.MulticastFrames = pmData.MulticastFrames
3772 }
3773 if pmData.CrcErroredFrames != errorCounterValue {
3774 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3775 } else {
3776 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3777 }
3778 if pmData.UndersizeFrames != errorCounterValue {
3779 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3780 } else {
3781 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3782 }
3783 if pmData.OversizeFrames != errorCounterValue {
3784 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3785 } else {
3786 pmDataOut.OversizeFrames = pmData.OversizeFrames
3787 }
3788 if pmData.Frames_64Octets != errorCounterValue {
3789 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3790 } else {
3791 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3792 }
3793 if pmData.Frames_65To_127Octets != errorCounterValue {
3794 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3795 } else {
3796 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3797 }
3798 if pmData.Frames_128To_255Octets != errorCounterValue {
3799 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3800 } else {
3801 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3802 }
3803 if pmData.Frames_256To_511Octets != errorCounterValue {
3804 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3805 } else {
3806 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3807 }
3808 if pmData.Frames_512To_1023Octets != errorCounterValue {
3809 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3810 } else {
3811 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3812 }
3813 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3814 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3815 } else {
3816 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3817 }
3818 } else {
3819 pmDataOut.DropEvents = pmDataIn["drop_events"]
3820 pmDataOut.Octets = pmDataIn["octets"]
3821 pmDataOut.Frames = pmDataIn["frames"]
3822 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3823 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3824 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3825 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3826 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3827 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3828 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3829 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3830 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3831 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3832 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3833 }
3834 return pmDataOut
3835}
3836
Himani Chawlaee10b542021-09-20 16:46:40 +05303837func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303838 controlBlock := make([]uint16, 8)
3839 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3840 controlBlock[0] = 0
3841 // Next two bytes are for the parent class ID
3842 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3843 // Next two bytes are for the parent me instance id
3844 controlBlock[2] = entityID
3845 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303846 if reset {
3847 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3848 } else {
3849 controlBlock[3] = 0
3850 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303851 // Next two bytes are for tca disable
3852 controlBlock[4] = 0x4000 //tca global disable
3853 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3854 if upstream {
3855 controlBlock[5] = 1 << 0
3856 } else {
3857 controlBlock[5] = (1 << 0) | (1 << 1)
3858 }
3859 // Next two bytes are for tci - does not matter here
3860 controlBlock[6] = 0
3861 // Next two bytes are for reserved bits - does not matter here
3862 controlBlock[7] = 0
3863 return controlBlock
3864}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003865
3866// PrepareForGarbageCollection - remove references to prepare for garbage collection
3867func (mm *OnuMetricsManager) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
3868 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
3869 mm.pDeviceHandler = nil
3870 mm.pOnuDeviceEntry = nil
3871}