blob: 2271864a2363a8a289b9a9c794f17eae23aaaf8a [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 {
Holger Hildebrandtabfef032022-02-25 12:40:20 +0000385 logger.Errorw(ctx, "error restoring pm data", log.Fields{"device-id": metricsManager.deviceID, "err": err})
Girish Gowdra50e56422021-06-01 16:46:04 -0700386 // 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 {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001022 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001023 }
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:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00001078 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"device-id": mm.deviceID, "msgType": msg.OmciMsg.MessageType})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001079
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:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002659 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"device-id": mm.deviceID, "groupName": g.GroupName})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002660 }
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:
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002673 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"device-id": mm.deviceID, "metricName": m.Name})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002674 }
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 {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002879 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"device-id": mm.deviceID,
2880 "groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002881 return err
2882 }
2883 // Update back to kv store
2884 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002885 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"device-id": mm.deviceID,
2886 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002887 return err
2888 }
Holger Hildebrandtabfef032022-02-25 12:40:20 +00002889 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID,
2890 "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002891
2892 return nil
2893}
2894
2895// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002896func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2897 mm.OnuMetricsManagerLock.Lock()
2898 defer mm.OnuMetricsManagerLock.Unlock()
2899 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002900 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002901 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2902 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002903 }
2904
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002905 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002906 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002907 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002908 // do not abort this procedure. continue to delete next group.
2909 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002910 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002911 }
2912 }
2913
2914 return nil
2915}
2916
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002917// ClearAllPmData clears all PM data associated with the device from KV store
2918func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
2919 mm.OnuMetricsManagerLock.Lock()
2920 defer mm.OnuMetricsManagerLock.Unlock()
2921 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002922 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002923 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2924 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002925 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002926 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002928 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002929 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002930 value = err
2931 // do not abort this procedure - continue to delete next group.
2932 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002933 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002934 }
Girish Gowdra0e533642021-03-02 22:02:51 -08002935 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002936 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002937 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002938 }
2939 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002940}
2941
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002942func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
2943 mm.OnuMetricsManagerLock.Lock()
2944 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002945 mm.omciProcessingActive = status
2946}
2947
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002948// updateTickGenerationStatus - TODO: add comment
2949func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
2950 mm.OnuMetricsManagerLock.Lock()
2951 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002952 mm.tickGenerationActive = status
2953}
2954
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002955// GetOmciProcessingStatus - TODO: add comment
2956func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
2957 mm.OnuMetricsManagerLock.RLock()
2958 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002959 return mm.omciProcessingActive
2960}
2961
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962// GetTickGenerationStatus - TODO: add comment
2963func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
2964 mm.OnuMetricsManagerLock.RLock()
2965 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002966 return mm.tickGenerationActive
2967}
2968
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002969func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002970 for _, ele := range slice {
2971 if ele == n {
2972 return slice
2973 }
2974 }
2975 return append(slice, n)
2976}
2977
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002978func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002979 for i, ele := range slice {
2980 if ele == n {
2981 return append(slice[:i], slice[i+1:]...)
2982 }
2983 }
2984 return slice
2985}
2986
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002987func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002988 for _, ele := range slice {
2989 if ele == n {
2990 return slice
2991 }
2992 }
2993 return append(slice, n)
2994}
2995
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002996func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002997 for i, ele := range slice {
2998 if ele == n {
2999 return append(slice[:i], slice[i+1:]...)
3000 }
3001 }
3002 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003003}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303004
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003005func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303006 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3007 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003008 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3009 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3010 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303011 Value, err := mm.extPmKvStore.Get(ctx, key)
3012 if err == nil {
3013 if Value != nil {
3014 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003015 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303016 tmpBytes, _ := kvstore.ToByte(Value.Value)
3017
3018 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003019 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303020 return false, err
3021 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003022 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303023 // We have found the data from db, no need to get through omci get message.
3024 mm.supportedEthernetFrameExtendedPMClass = data
3025 return true, nil
3026 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003027 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303028 return false, nil
3029 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003030 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303031 return false, err
3032}
3033
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003034func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303035 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
3036 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303037 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303038 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003039 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303040 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3041 if resp == me.Success || resp == me.InstanceExists {
3042 return true, nil
3043 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3044 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3045 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3046 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003047 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 +05303048 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3049 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003050 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303051 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003052 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303053 }
3054 return false, fmt.Errorf("timeout-while-waiting-for-response")
3055}
3056
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003057func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303058 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303059 // 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 +05303060 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303062 var entityID uint16
3063 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003064 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303065 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003066 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303067 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303068 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303069 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303070 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303071
3072 inner1:
3073 // retry ExtendedPmCreateAttempts times to create the instance of PM
3074 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003075 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3076 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3077 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303078 if err != nil {
3079 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003080 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303081 return false, err
3082 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303083 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3084 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303085 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303086 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303087 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303088 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303089 }
3090 break inner1
3091 } else if err != nil {
3092 if !supported {
3093 // Need to return immediately
3094 return false, err
3095 }
3096 //In case of failure, go for a retry
3097 }
3098 }
3099 if cnt == ExtendedPmCreateAttempts {
3100 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3101 return true, fmt.Errorf("unable-to-create-me")
3102 }
3103 }
3104 }
3105 return true, nil
3106}
3107
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003108func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3109 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3110 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3111 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303112 // check if we get the supported type me for ethernet frame extended pm class id
3113 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3114 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3115 }
3116 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3117 if err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003118 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303119 }
3120 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
Holger Hildebrandtabfef032022-02-25 12:40:20 +00003121 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"device-id": mm.deviceID, "err": err})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303122 }
3123}
3124
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003125func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303126 mm.onuEthernetFrameExtendedPmLock.Lock()
3127 mm.isDeviceReadyToCollectExtendedPmStats = true
3128 mm.onuEthernetFrameExtendedPmLock.Unlock()
3129}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003130
Himani Chawlaee10b542021-09-20 16:46:40 +05303131// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003132func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303133 //get the type of extended frame pm me supported by onu first
3134 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3135 if err != nil {
3136 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3137 return
3138 }
3139 if exist {
3140 // we have the me type, go ahead with the me type supported.
3141 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003142 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303143 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3144 return
3145 }
3146 mm.setAllExtPmMeCreatedFlag()
3147 return
3148 }
3149 // First try with 64 bit me
3150 // we have the me type, go ahead with the me type supported.
3151 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3152 if err != nil && !supported64Bit {
3153 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003154 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303155 "supported": supported64Bit})
3156 // Then Try with 32 bit type
3157 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003158 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303159 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3160 } else if supported32Bit {
3161 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3162 mm.putExtPmMeKvStore(ctx)
3163 mm.setAllExtPmMeCreatedFlag()
3164 }
3165 } else if err == nil && supported64Bit {
3166 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3167 mm.putExtPmMeKvStore(ctx)
3168 mm.setAllExtPmMeCreatedFlag()
3169 }
3170}
3171
Himani Chawlaee10b542021-09-20 16:46:40 +05303172func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3173 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3174 uniPortEntityID := entityID
3175 if upstream {
3176 uniPortEntityID = entityID - 0x100
3177 }
3178 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3179 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3180 mm.pDeviceHandler.GetOmciTimeout(), true,
3181 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3182 if err != nil {
3183 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3184 log.Fields{"device-id": mm.deviceID})
3185 return extension.GetValueResponse_INTERNAL_ERROR, err
3186 }
3187
3188 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3189 return extension.GetValueResponse_REASON_UNDEFINED, nil
3190 }
3191 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3192}
3193
3194func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3195 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
3196 select {
3197 case resp := <-mm.extendedPMMeResponseChan:
3198 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3199 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3200 if resp == me.Success {
3201 return true
3202 }
3203 return false
3204 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3205 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3206 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3207 }
3208 return false
3209}
3210
3211func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3212 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3213 className := "EthernetFrameExtendedPm64Bit"
3214 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3215 className = "EthernetFrameExtendedPm"
3216 }
3217 // Reset the counters if option is specified
3218 for entityID := range upstreamEntityMap {
3219 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3220 true)
3221 if err != nil {
3222 return errReason, err
3223 }
3224 }
3225
3226 for entityID := range downstreamEntityMap {
3227 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3228 true)
3229 if err != nil {
3230 return errReason, err
3231 }
3232 }
3233 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3234 // device itself.
3235 // Unset the reset bit if option is specified
3236 for entityID := range upstreamEntityMap {
3237 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3238 false)
3239 if err != nil {
3240 return errReason, err
3241 }
3242 }
3243
3244 for entityID := range downstreamEntityMap {
3245 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3246 false)
3247 if err != nil {
3248 return errReason, err
3249 }
3250 }
3251 return extension.GetValueResponse_REASON_UNDEFINED, nil
3252}
3253
3254func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3255 mm.onuEthernetFrameExtendedPmLock.Lock()
3256 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3257 mm.isEthernetFrameExtendedPmOperationOngoing = val
3258}
3259
3260func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3261 mm.onuEthernetFrameExtendedPmLock.Lock()
3262 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3263 return mm.isEthernetFrameExtendedPmOperationOngoing
3264}
3265
3266// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3267func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3268 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3269 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3270 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303271 return &extension.SingleGetValueResponse{
3272 Response: &extension.GetValueResponse{
3273 Status: extension.GetValueResponse_ERROR,
3274 ErrReason: reason,
3275 },
3276 }
3277 }
3278 mm.onuEthernetFrameExtendedPmLock.RLock()
3279 if !mm.isDeviceReadyToCollectExtendedPmStats {
3280 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303281 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303282 }
3283 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303284
3285 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3286 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3287 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3288 }
3289 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3290 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3291
3292 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3293 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3294 if onuInfo.IsUniIndex != nil {
3295 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3296 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3297 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3298 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3299 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3300 break
3301 }
3302 }
3303 if len(downstreamEntityMap) == 0 {
3304 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3305 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3306 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3307 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3308 }
3309 } else {
3310 // make a copy of all downstream and upstream maps in the local ones
3311 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3312 upstreamEntityMap[entityID] = meEnt
3313 }
3314 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3315 downstreamEntityMap[entityID] = meEnt
3316 }
3317 }
3318 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3319 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3320 // Reset the metrics first for all required me's
3321 if onuInfo.Reset_ {
3322 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3323 if err != nil {
3324 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3325 log.Fields{"device-id": mm.deviceID})
3326 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3327 }
3328 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303329 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3330 var pmUpstream extension.OmciEthernetFrameExtendedPm
3331 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303332 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3333 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3334 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3335 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303336 if !onuInfo.Reset_ {
3337 for entityID, meEnt := range upstreamEntityMap {
3338 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3339 var receivedMask uint16
3340 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3341 if receivedMask == 0 {
3342 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303343 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3344 // It might be possible that still some downstream pms are supported and hence we need to continue
3345 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3346 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303347 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303348 // Aggregate the result for upstream
3349 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3350 } else {
3351 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303352 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303353 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303354
Himani Chawlaee10b542021-09-20 16:46:40 +05303355 for entityID, meEnt := range downstreamEntityMap {
3356 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3357 var receivedMask uint16
3358 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303359 if receivedMask == 0 {
3360 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3361 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3362 // Stop collecting downstream counters for other ME's.
3363 break
3364 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303365 // Aggregate the result for downstream
3366 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3367 } else {
3368 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3369 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303370 }
3371 }
3372 singleValResp := extension.SingleGetValueResponse{
3373 Response: &extension.GetValueResponse{
3374 Status: extension.GetValueResponse_OK,
3375 Response: &extension.GetValueResponse_OnuCounters{
3376 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303377 Upstream: &pmUpstream,
3378 Downstream: &pmDownstream,
3379 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303380 },
3381 },
3382 },
3383 }
3384 return &singleValResp
3385}
3386
Himani Chawlaee10b542021-09-20 16:46:40 +05303387func (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 +05303388 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003389 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 +05303390
3391 classID = mm.supportedEthernetFrameExtendedPMClass
3392 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3393 if classID == me.EthernetFrameExtendedPmClassID {
3394 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3395 }
3396 ethPMData := make(map[string]uint64)
3397 var sumReceivedMask uint16
3398 for mask := range attributeMaskList {
3399 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3400 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003401 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303402 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303403 }
3404 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3405 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3406 //populate all counters as failure and return
3407 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3408 break
3409 }
3410 }
3411 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303412 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303413}
3414
3415// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003416func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303417 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3418 var meAttributes me.AttributeValueMap
3419 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003420 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303421 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003422 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303423 return extension.GetValueResponse_INTERNAL_ERROR, err
3424 }
3425 select {
3426 case meAttributes = <-mm.extendedPmMeChan:
3427 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003428 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3429 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303430 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003431 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303432 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3433 }
3434 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3435 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3436 *sumReceivedMask += mask
3437 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3438 } else {
3439 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3440 *sumReceivedMask += mask
3441 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3442 }
3443
3444 return extension.GetValueResponse_REASON_UNDEFINED, nil
3445}
3446
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003447func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303448 sourceMap := maskToEthernetFrameExtendedPM64Bit
3449 errorCounterValue := UnsupportedCounterValue64bit
3450 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3451 sourceMap = maskToEthernetFrameExtendedPM32Bit
3452 errorCounterValue = UnsupportedCounterValue32bit
3453 }
3454 for _, value := range sourceMap {
3455 for _, k := range value {
3456 if _, ok := ethFrameExtPMData[k]; !ok {
3457 ethFrameExtPMData[k] = errorCounterValue
3458 }
3459 }
3460 }
3461}
3462
3463// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003464func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303465 receivedMask := uint16(0)
3466 switch requestedAttributesMask {
3467 case 0x3F00:
3468 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3469 if _, ok := ethFrameExtPMData[k]; !ok {
3470 switch k {
3471 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003472 if val, ok := meAttributes[me.EthernetFrameExtendedPm_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303473 ethFrameExtPMData[k] = uint64(val.(uint32))
3474 receivedMask |= 0x2000
3475 } else if !ok {
3476 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3477 }
3478 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003479 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303480 ethFrameExtPMData[k] = uint64(val.(uint32))
3481 receivedMask |= 0x1000
3482 } else if !ok {
3483 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3484 }
3485 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003486 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303487 ethFrameExtPMData[k] = uint64(val.(uint32))
3488 receivedMask |= 0x800
3489 } else if !ok {
3490 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3491 }
3492 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003493 if val, ok := meAttributes[me.EthernetFrameExtendedPm_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303494 ethFrameExtPMData[k] = uint64(val.(uint32))
3495 receivedMask |= 0x400
3496 } else if !ok {
3497 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3498 }
3499 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003500 if val, ok := meAttributes[me.EthernetFrameExtendedPm_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303501 ethFrameExtPMData[k] = uint64(val.(uint32))
3502 receivedMask |= 0x200
3503 } else if !ok {
3504 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3505 }
3506 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003507 if val, ok := meAttributes[me.EthernetFrameExtendedPm_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303508 ethFrameExtPMData[k] = uint64(val.(uint32))
3509 receivedMask |= 0x100
3510 } else if !ok {
3511 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3512 }
3513 default:
3514 //do nothing
3515 }
3516 }
3517 }
3518 case 0x00FC:
3519 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3520 if _, ok := ethFrameExtPMData[k]; !ok {
3521 switch k {
3522 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003523 if val, ok := meAttributes[me.EthernetFrameExtendedPm_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303524 ethFrameExtPMData[k] = uint64(val.(uint32))
3525 receivedMask |= 0x80
3526 } else if !ok {
3527 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3528 }
3529 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003530 if val, ok := meAttributes[me.EthernetFrameExtendedPm_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303531 ethFrameExtPMData[k] = uint64(val.(uint32))
3532 receivedMask |= 0x40
3533 } else if !ok {
3534 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3535 }
3536 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003537 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303538 ethFrameExtPMData[k] = uint64(val.(uint32))
3539 receivedMask |= 0x20
3540 } else if !ok {
3541 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3542 }
3543 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003544 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303545 ethFrameExtPMData[k] = uint64(val.(uint32))
3546 receivedMask |= 0x10
3547 } else if !ok {
3548 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3549 }
3550 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003551 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303552 ethFrameExtPMData[k] = uint64(val.(uint32))
3553 receivedMask |= 0x8
3554 } else if !ok {
3555 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3556 }
3557 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003558 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303559 ethFrameExtPMData[k] = uint64(val.(uint32))
3560 receivedMask |= 0x4
3561 } else if !ok {
3562 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3563 }
3564 default:
3565 //do nothing
3566 }
3567 }
3568 }
3569 case 0x0003:
3570 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3571 if _, ok := ethFrameExtPMData[k]; !ok {
3572 switch k {
3573 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003574 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303575 ethFrameExtPMData[k] = uint64(val.(uint32))
3576 receivedMask |= 0x2
3577 } else if !ok {
3578 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3579 }
3580 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003581 if val, ok := meAttributes[me.EthernetFrameExtendedPm_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303582 ethFrameExtPMData[k] = uint64(val.(uint32))
3583 receivedMask |= 0x1
3584 } else if !ok {
3585 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3586 }
3587 default:
3588 //do nothing
3589 }
3590 }
3591 }
3592 default:
3593 //do nothing
3594 }
3595 return receivedMask
3596}
3597
3598// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003599func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303600 receivedMask := uint16(0)
3601 switch requestedAttributesMask {
3602 case 0x3800:
3603 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3604 if _, ok := ethFrameExtPMData[k]; !ok {
3605 switch k {
3606 case "drop_events":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003607 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_DropEvents]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303608 ethFrameExtPMData[k] = val.(uint64)
3609 receivedMask |= 0x2000
3610 } else if !ok {
3611 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3612 }
3613 case "octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003614 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303615 ethFrameExtPMData[k] = val.(uint64)
3616 receivedMask |= 0x1000
3617 } else if !ok {
3618 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3619 }
3620 case "frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003621 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303622 ethFrameExtPMData[k] = val.(uint64)
3623 receivedMask |= 0x800
3624 } else if !ok {
3625 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3626 }
3627 }
3628 }
3629 }
3630 case 0x0700:
3631 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3632 if _, ok := ethFrameExtPMData[k]; !ok {
3633 switch k {
3634 case "broadcast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003635 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_BroadcastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303636 ethFrameExtPMData[k] = val.(uint64)
3637 receivedMask |= 0x400
3638 } else if !ok {
3639 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3640 }
3641 case "multicast_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003642 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_MulticastFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303643 ethFrameExtPMData[k] = val.(uint64)
3644 receivedMask |= 0x200
3645 } else if !ok {
3646 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3647 }
3648 case "crc_errored_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003649 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_CrcErroredFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303650 ethFrameExtPMData[k] = val.(uint64)
3651 receivedMask |= 0x100
3652 } else if !ok {
3653 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3654 }
3655 }
3656 }
3657 }
3658 case 0x00E0:
3659 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3660 if _, ok := ethFrameExtPMData[k]; !ok {
3661 switch k {
3662 case "undersize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003663 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_UndersizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303664 ethFrameExtPMData[k] = val.(uint64)
3665 receivedMask |= 0x80
3666 } else if !ok {
3667 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3668 }
3669 case "oversize_frames":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003670 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_OversizeFrames]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303671 ethFrameExtPMData[k] = val.(uint64)
3672 receivedMask |= 0x40
3673 } else if !ok {
3674 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3675 }
3676 case "64_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003677 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames64Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303678 ethFrameExtPMData[k] = val.(uint64)
3679 receivedMask |= 0x20
3680 } else if !ok {
3681 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3682 }
3683 }
3684 }
3685 }
3686 case 0x001C:
3687 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3688 if _, ok := ethFrameExtPMData[k]; !ok {
3689 switch k {
3690 case "65_to_127_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003691 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames65To127Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303692 ethFrameExtPMData[k] = val.(uint64)
3693 receivedMask |= 0x10
3694 } else if !ok {
3695 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3696 }
3697 case "128_to_255_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003698 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames128To255Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303699 ethFrameExtPMData[k] = val.(uint64)
3700 receivedMask |= 0x8
3701 } else if !ok {
3702 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3703 }
3704 case "256_to_511_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003705 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames256To511Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303706 ethFrameExtPMData[k] = val.(uint64)
3707 receivedMask |= 0x4
3708 } else if !ok {
3709 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3710 }
3711 default:
3712 //do nothing
3713 }
3714 }
3715 }
3716 case 0x0003:
3717 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3718 if _, ok := ethFrameExtPMData[k]; !ok {
3719 switch k {
3720 case "512_to_1023_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003721 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames512To1023Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303722 ethFrameExtPMData[k] = val.(uint64)
3723 receivedMask |= 0x2
3724 } else if !ok {
3725 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3726 }
3727 case "1024_to_1518_octets":
Holger Hildebrandt3ac49bd2022-02-07 17:46:43 +00003728 if val, ok := meAttributes[me.EthernetFrameExtendedPm64Bit_Frames1024To1518Octets]; ok && val != nil {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303729 ethFrameExtPMData[k] = val.(uint64)
3730 receivedMask |= 0x1
3731 } else if !ok {
3732 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3733 }
3734 default:
3735 //do nothing
3736 }
3737 }
3738 }
3739 }
3740 return receivedMask
3741}
3742
Himani Chawlaee10b542021-09-20 16:46:40 +05303743func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3744 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303745 errorCounterValue := UnsupportedCounterValue64bit
3746 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3747 errorCounterValue = UnsupportedCounterValue32bit
3748 }
3749 var pmDataOut extension.OmciEthernetFrameExtendedPm
3750 if aggregate {
3751 if pmData.DropEvents != errorCounterValue {
3752 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3753 } else {
3754 pmDataOut.DropEvents = pmData.DropEvents
3755 }
3756 if pmData.Octets != errorCounterValue {
3757 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3758 } else {
3759 pmDataOut.Octets = pmData.Octets
3760 }
3761 if pmData.Frames != errorCounterValue {
3762 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3763 } else {
3764 pmDataOut.Frames = pmData.Frames
3765 }
3766 if pmData.BroadcastFrames != errorCounterValue {
3767 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3768 } else {
3769 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3770 }
3771 if pmData.MulticastFrames != errorCounterValue {
3772 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3773 } else {
3774 pmDataOut.MulticastFrames = pmData.MulticastFrames
3775 }
3776 if pmData.CrcErroredFrames != errorCounterValue {
3777 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3778 } else {
3779 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3780 }
3781 if pmData.UndersizeFrames != errorCounterValue {
3782 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3783 } else {
3784 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3785 }
3786 if pmData.OversizeFrames != errorCounterValue {
3787 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3788 } else {
3789 pmDataOut.OversizeFrames = pmData.OversizeFrames
3790 }
3791 if pmData.Frames_64Octets != errorCounterValue {
3792 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3793 } else {
3794 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3795 }
3796 if pmData.Frames_65To_127Octets != errorCounterValue {
3797 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3798 } else {
3799 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3800 }
3801 if pmData.Frames_128To_255Octets != errorCounterValue {
3802 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3803 } else {
3804 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3805 }
3806 if pmData.Frames_256To_511Octets != errorCounterValue {
3807 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3808 } else {
3809 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3810 }
3811 if pmData.Frames_512To_1023Octets != errorCounterValue {
3812 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3813 } else {
3814 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3815 }
3816 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3817 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3818 } else {
3819 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3820 }
3821 } else {
3822 pmDataOut.DropEvents = pmDataIn["drop_events"]
3823 pmDataOut.Octets = pmDataIn["octets"]
3824 pmDataOut.Frames = pmDataIn["frames"]
3825 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3826 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3827 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3828 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3829 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3830 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3831 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3832 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3833 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3834 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3835 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3836 }
3837 return pmDataOut
3838}
3839
Himani Chawlaee10b542021-09-20 16:46:40 +05303840func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303841 controlBlock := make([]uint16, 8)
3842 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3843 controlBlock[0] = 0
3844 // Next two bytes are for the parent class ID
3845 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3846 // Next two bytes are for the parent me instance id
3847 controlBlock[2] = entityID
3848 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303849 if reset {
3850 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3851 } else {
3852 controlBlock[3] = 0
3853 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303854 // Next two bytes are for tca disable
3855 controlBlock[4] = 0x4000 //tca global disable
3856 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3857 if upstream {
3858 controlBlock[5] = 1 << 0
3859 } else {
3860 controlBlock[5] = (1 << 0) | (1 << 1)
3861 }
3862 // Next two bytes are for tci - does not matter here
3863 controlBlock[6] = 0
3864 // Next two bytes are for reserved bits - does not matter here
3865 controlBlock[7] = 0
3866 return controlBlock
3867}
Holger Hildebrandte7cc6092022-02-01 11:37:03 +00003868
3869// PrepareForGarbageCollection - remove references to prepare for garbage collection
3870func (mm *OnuMetricsManager) PrepareForGarbageCollection(ctx context.Context, aDeviceID string) {
3871 logger.Debugw(ctx, "prepare for garbage collection", log.Fields{"device-id": aDeviceID})
3872 mm.pDeviceHandler = nil
3873 mm.pOnuDeviceEntry = nil
3874}