blob: 5ed462a85ea27abb8f7f9d470e444a9cb3b7191f [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
77 dropEvents = "DropEvents"
78 octets = "Octets"
79 frames = "Frames"
80 broadcastFrames = "BroadcastFrames"
81 multicastFrames = "MulticastFrames"
82 crcErroredFrames = "CrcErroredFrames"
83 undersizeFrames = "UndersizeFrames"
84 oversizeFrames = "OversizeFrames"
85 frames64Octets = "Frames64Octets"
86 frames65To127Octets = "Frames65To127Octets"
87 frames128To255Octets = "Frames128To255Octets"
88 frames256To511Octets = "Frames256To511Octets"
89 frames512To1023Octets = "Frames512To1023Octets"
90 frames1024To1518Octets = "Frames1024To1518Octets"
91)
92
Girish Gowdra5a7c4922021-01-22 18:33:41 -080093// OpticalPowerGroupMetrics are supported optical pm names
94var OpticalPowerGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrae20a4f62021-03-09 16:06:23 -080095 "ani_g_instance_id": voltha.PmConfig_CONTEXT,
96 "transmit_power_dBm": voltha.PmConfig_GAUGE,
97 "receive_power_dBm": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -080098}
99
100// OpticalPowerGroupMetrics specific constants
101const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800102 OpticalPowerGroupMetricName = "PON_Optical"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800103 OpticalPowerGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
104 OpticalPowerMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
105)
106
107// UniStatusGroupMetrics are supported UNI status names
108var UniStatusGroupMetrics = map[string]voltha.PmConfig_PmType{
Girish Gowdrad3436802021-06-28 13:15:40 -0700109 "uni_port_no": voltha.PmConfig_CONTEXT,
110 "me_class_id": voltha.PmConfig_CONTEXT,
111 "entity_id": voltha.PmConfig_CONTEXT,
112 "configuration_ind": voltha.PmConfig_GAUGE,
113 "oper_status": voltha.PmConfig_GAUGE,
114 "uni_admin_state": voltha.PmConfig_GAUGE,
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800115}
116
117// UniStatusGroupMetrics specific constants
118const (
Girish Gowdrae0140f02021-02-02 16:55:09 -0800119 UniStatusGroupMetricName = "UNI_Status"
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800120 UniStatusGroupMetricEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
121 UniStatusMetricGroupCollectionFrequency = 5 * 60 // unit in seconds. This setting can be changed from voltha NBI PmConfig configuration
122)
123
Girish Gowdrae0140f02021-02-02 16:55:09 -0800124// *** Classical L2 PM Counters begin ***
125
126// EthernetBridgeHistory are supported ethernet bridge history counters fetched from
127// Ethernet Frame Performance Monitoring History Data Downstream and Ethernet Frame Performance Monitoring History Data Upstream MEs.
128var EthernetBridgeHistory = map[string]voltha.PmConfig_PmType{
129 "class_id": voltha.PmConfig_CONTEXT,
130 "entity_id": voltha.PmConfig_CONTEXT,
131 "interval_end_time": voltha.PmConfig_CONTEXT,
132 "parent_class_id": voltha.PmConfig_CONTEXT,
133 "parent_entity_id": voltha.PmConfig_CONTEXT,
134 "upstream": voltha.PmConfig_CONTEXT,
135
136 "drop_events": voltha.PmConfig_COUNTER,
137 "octets": voltha.PmConfig_COUNTER,
138 "packets": voltha.PmConfig_COUNTER,
139 "broadcast_packets": voltha.PmConfig_COUNTER,
140 "multicast_packets": voltha.PmConfig_COUNTER,
141 "crc_errored_packets": voltha.PmConfig_COUNTER,
142 "undersize_packets": voltha.PmConfig_COUNTER,
143 "oversize_packets": voltha.PmConfig_COUNTER,
144 "64_octets": voltha.PmConfig_COUNTER,
145 "65_to_127_octets": voltha.PmConfig_COUNTER,
146 "128_to_255_octets": voltha.PmConfig_COUNTER,
147 "256_to_511_octets": voltha.PmConfig_COUNTER,
148 "512_to_1023_octets": voltha.PmConfig_COUNTER,
149 "1024_to_1518_octets": voltha.PmConfig_COUNTER,
150}
151
152// EthernetUniHistory are supported ethernet uni history counters fetched from
153// Ethernet Performance Monitoring History Data ME.
154var EthernetUniHistory = map[string]voltha.PmConfig_PmType{
155 "class_id": voltha.PmConfig_CONTEXT,
156 "entity_id": voltha.PmConfig_CONTEXT,
157 "interval_end_time": voltha.PmConfig_CONTEXT,
158
159 "fcs_errors": voltha.PmConfig_COUNTER,
160 "excessive_collision_counter": voltha.PmConfig_COUNTER,
161 "late_collision_counter": voltha.PmConfig_COUNTER,
162 "frames_too_long": voltha.PmConfig_COUNTER,
163 "buffer_overflows_on_rx": voltha.PmConfig_COUNTER,
164 "buffer_overflows_on_tx": voltha.PmConfig_COUNTER,
165 "single_collision_frame_counter": voltha.PmConfig_COUNTER,
166 "multiple_collisions_frame_counter": voltha.PmConfig_COUNTER,
167 "sqe_counter": voltha.PmConfig_COUNTER,
168 "deferred_tx_counter": voltha.PmConfig_COUNTER,
169 "internal_mac_tx_error_counter": voltha.PmConfig_COUNTER,
170 "carrier_sense_error_counter": voltha.PmConfig_COUNTER,
171 "alignment_error_counter": voltha.PmConfig_COUNTER,
172 "internal_mac_rx_error_counter": voltha.PmConfig_COUNTER,
173}
174
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800175// FecHistory is supported FEC Performance Monitoring History Data related metrics
176var FecHistory = 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 "corrected_bytes": voltha.PmConfig_COUNTER,
182 "corrected_code_words": voltha.PmConfig_COUNTER,
183 "uncorrectable_code_words": voltha.PmConfig_COUNTER,
184 "total_code_words": voltha.PmConfig_COUNTER,
185 "fec_seconds": voltha.PmConfig_COUNTER,
186}
187
188// GemPortHistory is supported GEM Port Network Ctp Performance Monitoring History Data
189// related metrics
190var GemPortHistory = map[string]voltha.PmConfig_PmType{
191 "class_id": voltha.PmConfig_CONTEXT,
192 "entity_id": voltha.PmConfig_CONTEXT,
193 "interval_end_time": voltha.PmConfig_CONTEXT,
194
195 "transmitted_gem_frames": voltha.PmConfig_COUNTER,
196 "received_gem_frames": voltha.PmConfig_COUNTER,
197 "received_payload_bytes": voltha.PmConfig_COUNTER,
198 "transmitted_payload_bytes": voltha.PmConfig_COUNTER,
199 "encryption_key_errors": voltha.PmConfig_COUNTER,
200}
201
Himani Chawla43f95ff2021-06-03 00:24:12 +0530202var maskToEthernetFrameExtendedPM32Bit = map[uint16][]string{
203 0x3F00: {"drop_events", "octets", "frames", "broadcast_frames", "multicast_frames", "crc_errored_frames"},
204 0x00FC: {"undersize_frames", "oversize_frames", "64_octets", "65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
205 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
206}
207
208var maskToEthernetFrameExtendedPM64Bit = map[uint16][]string{
209 0x3800: {"drop_events", "octets", "frames"},
210 0x0700: {"broadcast_frames", "multicast_frames", "crc_errored_frames"},
211 0x00E0: {"undersize_frames", "oversize_frames", "64_octets"},
212 0x001C: {"65_to_127_octets", "128_to_255_octets", "256_to_511_octets"},
213 0x0003: {"512_to_1023_octets", "1024_to_1518_octets"},
214}
215
Girish Gowdrae0140f02021-02-02 16:55:09 -0800216// Constants specific for L2 PM collection
217const (
218 L2PmCollectionInterval = 15 * 60 // Unit in seconds. Do not change this as this fixed by OMCI specification for L2 PM counters
219 SyncTimeRetryInterval = 15 // Unit seconds
220 L2PmCreateAttempts = 3
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800221 L2PmDeleteAttempts = 3
Girish Gowdrae0140f02021-02-02 16:55:09 -0800222 L2PmCollectAttempts = 3
Girish Gowdra453750f2021-02-16 16:36:46 -0800223 // Per Table 11.2.9-1 – OMCI baseline message limitations in G.988 spec, the max GET Response
224 // payload size is 25. We define 24 (one less) to allow for dynamic insertion of IntervalEndTime
225 // attribute (1 byte) in L2 PM GET Requests.
Himani Chawla43f95ff2021-06-03 00:24:12 +0530226 MaxL2PMGetPayLoadSize = 24
227 MaxEthernetFrameExtPmPayloadSize = 25
Girish Gowdrae0140f02021-02-02 16:55:09 -0800228)
229
230// EthernetUniHistoryName specific constants
231const (
232 EthernetBridgeHistoryName = "Ethernet_Bridge_Port_History"
233 EthernetBridgeHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
234 EthernetBridgeHistoryFrequency = L2PmCollectionInterval
235)
236
237// EthernetBridgeHistory specific constants
238const (
239 EthernetUniHistoryName = "Ethernet_UNI_History"
240 EthernetUniHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
241 EthernetUniHistoryFrequency = L2PmCollectionInterval
242)
243
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800244// FecHistory specific constants
245const (
246 FecHistoryName = "FEC_History"
247 FecHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
248 FecHistoryFrequency = L2PmCollectionInterval
249)
250
251// GemPortHistory specific constants
252const (
253 GemPortHistoryName = "GEM_Port_History"
254 GemPortHistoryEnabled = true // This setting can be changed from voltha NBI PmConfig configuration
255 GemPortHistoryFrequency = L2PmCollectionInterval
256)
257
Holger Hildebrandt60652202021-11-02 11:09:36 +0000258// CPmKvStorePrefixBase - kv store base path of ONU specific PM data
259const CPmKvStorePrefixBase = cmn.CBasePathOnuKVStore + "/pm-data" // <some-base-path>/openonu/pm-data
260
Girish Gowdra0e533642021-03-02 22:02:51 -0800261// KV Store related constants
262const (
Holger Hildebrandt60652202021-11-02 11:09:36 +0000263 cPmKvStorePrefix = CPmKvStorePrefixBase + "/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
Himani Chawla43f95ff2021-06-03 00:24:12 +0530264 cPmAdd = "add"
265 cPmAdded = "added"
266 cPmRemove = "remove"
267 cPmRemoved = "removed"
268 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800269)
270
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800271// Defines the type for generic metric population function
272type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
273
Girish Gowdrae0140f02021-02-02 16:55:09 -0800274// *** Classical L2 PM Counters end ***
275
Girish Gowdra0e533642021-03-02 22:02:51 -0800276type pmMEData struct {
277 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
278 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
279 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
280}
281
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800282type groupMetric struct {
283 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000284 Enabled bool
285 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800286 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000287 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
288 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800289 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800290 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800291}
292
293type standaloneMetric struct {
294 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000295 Enabled bool
296 Frequency uint32 // valid only if FrequencyOverride is enabled.
297 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800298}
299
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000300// OnuMetricsManager - TODO: add comment
301type OnuMetricsManager struct {
302 deviceID string
303 pDeviceHandler cmn.IdeviceHandler
304 pOnuDeviceEntry cmn.IonuDeviceEntry
305 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800306
Himani Chawlaee10b542021-09-20 16:46:40 +0530307 opticalMetricsChan chan me.AttributeValueMap
308 uniStatusMetricsChan chan me.AttributeValueMap
309 l2PmChan chan me.AttributeValueMap
310 extendedPmMeChan chan me.AttributeValueMap
311 syncTimeResponseChan chan bool // true is success, false is fail
312 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
313 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800314
315 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
316 l2PmToDelete []string // list of L2 PMs to delete
317 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800318
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000319 GroupMetricMap map[string]*groupMetric
320 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800321
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000322 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700323 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800324
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000325 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700326 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800327
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000328 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800329
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000330 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800331
332 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530333
334 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530335 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
336 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530337 extPmKvStore *db.Backend
338 onuEthernetFrameExtendedPmLock sync.RWMutex
339 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530340 isEthernetFrameExtendedPmOperationOngoing bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800341}
342
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000343// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800344// The metrics manager module is responsible for configuration and management of individual and group metrics.
345// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
346// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
347// the collection interval configurable.
348// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
349// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000350func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800351
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000352 var metricsManager OnuMetricsManager
353 metricsManager.deviceID = dh.GetDeviceID()
354 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800355 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000356 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800357
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000358 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800359 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
360 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800361 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530362 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800363
364 metricsManager.syncTimeResponseChan = make(chan bool)
365 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530366 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800367
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000368 metricsManager.StopProcessingOmciResponses = make(chan bool)
369 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800370
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000371 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
372 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800373
Himani Chawlac77d5372021-07-12 15:42:26 +0530374 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
375 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530376
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000377 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 -0800378 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800379 }
380
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800381 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800382
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800383 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800384 return nil
385 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800386
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800387 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000388 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800389
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000390 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
391 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800392 if metricsManager.pmKvStore == nil {
393 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000394 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800395 return nil
396 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700397 // restore data from KV store
398 if err := metricsManager.restorePmData(ctx); err != nil {
399 logger.Errorw(ctx, "error restoring pm data", log.Fields{"err": err})
400 // we continue given that it does not effect the actual services for the ONU,
401 // but there may be some negative effect on PM collection (there may be some mismatch in
402 // the actual PM config and what is present on the device).
403 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800404
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000405 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
406 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530407 if metricsManager.extPmKvStore == nil {
408 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000409 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530410 return nil
411 }
412
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000413 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800414 return &metricsManager
415}
416
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000417// InitializeMetricCollectionTime - TODO: add comment
418func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
419 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
420 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
421 mm.OnuMetricsManagerLock.Lock()
422 defer mm.OnuMetricsManagerLock.Unlock()
423 for _, v := range mm.GroupMetricMap {
424 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
425 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800426 }
427 }
428
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000429 for _, v := range mm.StandaloneMetricMap {
430 if v.Enabled {
431 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800432 }
433 }
434 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000435 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
436 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800437 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000438 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800439}
440
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000441// UpdateDefaultFrequency - TODO: add comment
442func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800443 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800444 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800445 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
446 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
447 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000448 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
449 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
450 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
451 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 -0800452 return nil
453}
454
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000455// UpdateGroupFreq - TODO: add comment
456func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800457 var newGroupFreq uint32
458 found := false
459 groupSliceIdx := 0
460 var group *voltha.PmGroupConfig
461 for groupSliceIdx, group = range pmConfigs.Groups {
462 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800463 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
464 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
465 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
466 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800467 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800468 newGroupFreq = group.GroupFreq
469 found = true
470 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800471 }
472 }
473 // if not found update group freq and next collection interval for the group
474 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000475 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800476 return fmt.Errorf("group-name-not-found-%v", aGroupName)
477 }
478
479 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000480 mm.OnuMetricsManagerLock.Lock()
481 defer mm.OnuMetricsManagerLock.Unlock()
482 for k, v := range mm.GroupMetricMap {
483 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
484 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800485 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000486 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800487 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000488 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800489 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000490 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800491 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800492 }
493 }
494 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000495 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800496 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
497 }
498 return nil
499}
500
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000501// UpdateMetricFreq - TODO: add comment
502func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800503 var newMetricFreq uint32
504 found := false
505 metricSliceIdx := 0
506 var metric *voltha.PmConfig
507 for metricSliceIdx, metric = range pmConfigs.Metrics {
508 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800509 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
510 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
511 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
512 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800513 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800514 newMetricFreq = metric.SampleFreq
515 found = true
516 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800517 }
518 }
519 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000520 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800521 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
522 }
523
524 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000525 mm.OnuMetricsManagerLock.Lock()
526 defer mm.OnuMetricsManagerLock.Unlock()
527 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800528 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000529 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800530 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000531 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800532 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000533 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000535 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800536 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800537 }
538 }
539 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000540 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800541 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
542 }
543 return nil
544}
545
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000546// UpdateGroupSupport - TODO: add comment
547func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800548 groupSliceIdx := 0
549 var group *voltha.PmGroupConfig
550
551 for groupSliceIdx, group = range pmConfigs.Groups {
552 if group.GroupName == aGroupName {
553 break
554 }
555 }
556 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000557 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800558 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
559 }
560
561 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000562 mm.OnuMetricsManagerLock.Lock()
563 defer mm.OnuMetricsManagerLock.Unlock()
564 for k, v := range mm.GroupMetricMap {
565 if k == aGroupName && v.Enabled != group.Enabled {
566 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
567 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800568 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000569 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800570 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800571 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800572 // 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 -0800573 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
574
575 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
576 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
577 // take further action
578 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800579 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800580 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000581 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
582 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 }
584 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000585 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800586 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800587 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800588 // 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 -0800589 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
590
591 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
592 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
593 // take further action
594 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800595 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800596 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800597 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800598 }
599 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000600 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800601 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000602 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800603 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000604 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 -0800605 }
606 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800607 }
608 }
609
610 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000611 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800612 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
613 }
614 return nil
615}
616
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000617// UpdateMetricSupport - TODO: add comment
618func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800619 metricSliceIdx := 0
620 var metric *voltha.PmConfig
621
622 for metricSliceIdx, metric = range pmConfigs.Metrics {
623 if metric.Name == aMetricName {
624 break
625 }
626 }
627
628 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000629 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800630 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
631 }
632
633 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000634 mm.OnuMetricsManagerLock.Lock()
635 defer mm.OnuMetricsManagerLock.Unlock()
636 for k, v := range mm.StandaloneMetricMap {
637 if k == aMetricName && v.Enabled != metric.Enabled {
638 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
639 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800640 // 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 +0000641 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
642 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800643 }
644 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000645 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 -0800646 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800647 }
648 }
649 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000650 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800651 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
652 }
653 return nil
654}
655
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000656// CollectAllGroupAndStandaloneMetrics - TODO: add comment
657func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
658 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800659 go mm.collectAllGroupMetrics(ctx)
660 } else {
661 go mm.collectAllStandaloneMetrics(ctx)
662 }
663}
664
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000665func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800666 go func() {
667 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300668 metricInfo, err := mm.collectOpticalMetrics(ctx)
669 if err != nil {
670 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000671 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300672 return
673 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800674 if metricInfo != nil {
675 mm.publishMetrics(ctx, metricInfo)
676 }
677 }()
678
679 go func() {
680 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300681 metricInfo, err := mm.collectUniStatusMetrics(ctx)
682 if err != nil {
683 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000684 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300685 return
686 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800687 if metricInfo != nil {
688 mm.publishMetrics(ctx, metricInfo)
689 }
690 }()
691
692 // Add more here
693}
694
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000695func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800696 // None exists as of now, add when available here
697}
698
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000699// CollectGroupMetric - TODO: add comment
700func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800701 switch groupName {
702 case OpticalPowerGroupMetricName:
703 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300704 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800705 mm.publishMetrics(ctx, mi)
706 }
707 }()
708 case UniStatusGroupMetricName:
709 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300710 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800711 mm.publishMetrics(ctx, mi)
712 }
713 }()
714 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000715 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800716 }
717}
718
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000719// CollectStandaloneMetric - TODO: add comment
720func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800721 switch metricName {
722 // None exist as of now, add when available
723 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000724 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800725 }
726}
727
728// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000729func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
730 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800731
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000732 mm.OnuMetricsManagerLock.RLock()
733 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
734 mm.OnuMetricsManagerLock.RUnlock()
735 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300736 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800737 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000738 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800739
Girish Gowdrae09a6202021-01-12 18:10:59 -0800740 var metricInfoSlice []*voltha.MetricInformation
741 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000742 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
743 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
744 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800745
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800746 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800747 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800748 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800749 Ts: float64(raisedTs),
750 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000751 DeviceId: mm.deviceID,
752 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
753 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800754 }
755
Girish Gowdrae09a6202021-01-12 18:10:59 -0800756 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000757 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800758loop:
759 for _, anigInstID := range anigInstKeys {
760 var meAttributes me.AttributeValueMap
761 opticalMetrics := make(map[string]float32)
762 // Get the ANI-G instance optical power attributes
763 requestedAttributes := me.AttributeValueMap{"OpticalSignalLevel": 0, "TransmitOpticalLevel": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000764 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300765 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000766 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
767 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300768 return nil, err
769 }
770
771 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800772 select {
773 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000774 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
775 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
776 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 -0800777 // The metrics will be empty in this case
778 break loop
779 }
780 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800781 for k := range OpticalPowerGroupMetrics {
782 switch k {
783 case "ani_g_instance_id":
784 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
785 opticalMetrics[k] = float32(val.(uint16))
786 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800787 case "transmit_power_dBm":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800788 if val, ok := meAttributes["TransmitOpticalLevel"]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000789 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 -0800790 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800791 case "receive_power_dBm":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800792 if val, ok := meAttributes["OpticalSignalLevel"]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000793 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 -0800794 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800795 default:
796 // do nothing
797 }
798 }
799 }
800 // create slice of metrics given that there could be more than one ANI-G instance and
801 // optical metrics are collected per ANI-G instance
802 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
803 metricInfoSlice = append(metricInfoSlice, &metricInfo)
804 }
805
ozgecanetsiab36ed572021-04-01 10:38:48 +0300806 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800807}
808
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800809// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800810// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000811func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
812 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
813 mm.OnuMetricsManagerLock.RLock()
814 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
815 mm.OnuMetricsManagerLock.RUnlock()
816 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300817 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800818 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000819 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800820
Girish Gowdrae09a6202021-01-12 18:10:59 -0800821 var metricInfoSlice []*voltha.MetricInformation
822 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000823 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
824 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
825 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800826
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800827 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800828 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700829 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800830 Ts: float64(raisedTs),
831 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000832 DeviceId: mm.deviceID,
833 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
834 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800835 }
836
Girish Gowdrae09a6202021-01-12 18:10:59 -0800837 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000838 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800839loop1:
840 for _, unigInstID := range unigInstKeys {
841 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
842 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
843 unigMetrics := make(map[string]float32)
844 var meAttributes me.AttributeValueMap
845 // Get the UNI-G instance optical power attributes
846 requestedAttributes := me.AttributeValueMap{"AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000847 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300848 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000849 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
850 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300851 return nil, err
852 }
853 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800854 // Wait for metrics or timeout
855 select {
856 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000857 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
858 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
859 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 -0800860 // The metrics could be empty in this case
861 break loop1
862 }
863 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800864 for k := range UniStatusGroupMetrics {
865 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800866 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800867 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
868 unigMetrics[k] = float32(val.(byte))
869 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800870 default:
871 // do nothing
872 }
873 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800874 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800875 entityID := val.(uint16)
876 unigMetrics["entity_id"] = float32(entityID)
877 // 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 +0000878 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
879 if uni.EntityID == entityID {
880 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700881 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800882 }
883 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800884 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700885 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800886
Girish Gowdrae09a6202021-01-12 18:10:59 -0800887 // create slice of metrics given that there could be more than one UNI-G instance
888 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
889 metricInfoSlice = append(metricInfoSlice, &metricInfo)
890 }
891 }
892
893 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000894 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800895loop2:
896 for _, pptpInstID := range pptpInstKeys {
897 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
898 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
899 var meAttributes me.AttributeValueMap
900 pptpMetrics := make(map[string]float32)
901
Girish Gowdrad3436802021-06-28 13:15:40 -0700902 requestedAttributes := me.AttributeValueMap{"ConfigurationInd": 0, "OperationalState": 0, "AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000903 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID, pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300904 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000905 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
906 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300907 return nil, err
908 }
909 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800910 // Wait for metrics or timeout
911 select {
912 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000913 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
914 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
915 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 -0800916 // The metrics could be empty in this case
917 break loop2
918 }
919
920 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800921 for k := range UniStatusGroupMetrics {
922 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700923 case "configuration_ind":
924 if val, ok := meAttributes["ConfigurationInd"]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800925 pptpMetrics[k] = float32(val.(byte))
926 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800927 case "oper_status":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800928 if val, ok := meAttributes["OperationalState"]; ok && val != nil {
929 pptpMetrics[k] = float32(val.(byte))
930 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800931 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800932 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
933 pptpMetrics[k] = float32(val.(byte))
934 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800935 default:
936 // do nothing
937 }
938 }
939 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800940 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800941 entityID := val.(uint16)
942 pptpMetrics["entity_id"] = float32(entityID)
943 // 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 +0000944 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
945 if uni.EntityID == entityID {
946 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700947 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800948 }
949 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800950 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700951 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800952
Girish Gowdrae09a6202021-01-12 18:10:59 -0800953 // create slice of metrics given that there could be more than one PPTP instance and
954 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
955 metricInfoSlice = append(metricInfoSlice, &metricInfo)
956 }
957
958 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000959 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800960loop3:
961 for _, veipInstID := range veipInstKeys {
962 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
963 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
964 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800965 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800966
967 requestedAttributes := me.AttributeValueMap{"OperationalState": 0, "AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000968 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300969 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000970 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
971 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300972 return nil, err
973 }
974 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800975 // Wait for metrics or timeout
976 select {
977 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000978 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
979 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
980 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 -0800981 // The metrics could be empty in this case
982 break loop3
983 }
984
985 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800986 for k := range UniStatusGroupMetrics {
987 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800988 case "oper_status":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800989 if val, ok := meAttributes["OperationalState"]; ok && val != nil {
990 veipMetrics[k] = float32(val.(byte))
991 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800992 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800993 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
994 veipMetrics[k] = float32(val.(byte))
995 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800996 default:
997 // do nothing
998 }
999 }
1000 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001001
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001002 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001003 entityID := val.(uint16)
1004 veipMetrics["entity_id"] = float32(entityID)
1005 // 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 +00001006 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1007 if uni.EntityID == entityID {
1008 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001009 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001010 }
1011 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001012 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001013 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001014
Girish Gowdrae09a6202021-01-12 18:10:59 -08001015 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001016 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001017 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1018 }
1019
ozgecanetsiab36ed572021-04-01 10:38:48 +03001020 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001021}
1022
1023// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001024func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001025 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001026 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001027 ke.SliceData = metricInfo
1028 ke.Type = voltha.KpiEventType_slice
1029 ke.Ts = float64(ts)
1030
Himani Chawlaf9768882021-12-01 00:18:58 +05301031 if err := mm.pDeviceHandler.GetEventProxy().SendKpiEvent(ctx, "STATS_PUBLISH_EVENT", &ke, voltha.EventCategory_EQUIPMENT, voltha.EventSubCategory_ONU, ts); err != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001032 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"err": err})
1033 }
1034}
1035
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001036// ProcessOmciMessages - TODO: add comment
1037func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context) {
1038 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 -08001039 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001040 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001041 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001042 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001043 // is stopped - as a result of ONU going down.
1044 mm.flushMetricCollectionChannels(ctx)
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001045 mm.updateOmciProcessingStatus(true)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001046 for {
1047 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001048 case <-mm.StopProcessingOmciResponses: // stop this routine
1049 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 -07001050 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001051 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001052 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001053 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001054 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001055 continue
1056 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001057 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001058
1059 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001060 case cmn.OMCI:
1061 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001062 mm.handleOmciMessage(ctx, msg)
1063 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001064 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001065 }
1066 }
1067 }
1068}
1069
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001070func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1071 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001072 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1073 switch msg.OmciMsg.MessageType {
1074 case omci.GetResponseType:
1075 //TODO: error handling
1076 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001077 case omci.SynchronizeTimeResponseType:
1078 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1079 case omci.CreateResponseType:
1080 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1081 case omci.DeleteResponseType:
1082 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301083 case omci.GetCurrentDataResponseType:
1084 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301085 case omci.SetResponseType:
1086 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001087 default:
1088 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"msgType": msg.OmciMsg.MessageType})
1089
1090 }
1091}
1092
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001093func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001094 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1095 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001096 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1097 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001098 }
1099 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1100 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001101 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1102 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001103 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001104 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 -08001105 if msgObj.Result == me.Success {
1106 meAttributes := msgObj.Attributes
1107 switch msgObj.EntityClass {
1108 case me.AniGClassID:
1109 mm.opticalMetricsChan <- meAttributes
1110 return nil
1111 case me.UniGClassID:
1112 mm.uniStatusMetricsChan <- meAttributes
1113 return nil
1114 case me.PhysicalPathTerminationPointEthernetUniClassID:
1115 mm.uniStatusMetricsChan <- meAttributes
1116 return nil
1117 case me.VirtualEthernetInterfacePointClassID:
1118 mm.uniStatusMetricsChan <- meAttributes
1119 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001120 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1121 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001122 me.EthernetPerformanceMonitoringHistoryDataClassID,
1123 me.FecPerformanceMonitoringHistoryDataClassID,
1124 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001125 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301126 return nil
1127 case me.EthernetFrameExtendedPmClassID,
1128 me.EthernetFrameExtendedPm64BitClassID:
1129 mm.extendedPmMeChan <- meAttributes
1130 return nil
1131 default:
1132 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001133 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301134 }
1135 } else {
1136 meAttributes := msgObj.Attributes
1137 switch msgObj.EntityClass {
1138 case me.EthernetFrameExtendedPmClassID,
1139 me.EthernetFrameExtendedPm64BitClassID:
1140 // not all counters may be supported in which case we have seen some ONUs throwing
1141 // AttributeFailure error code, while correctly populating other counters it supports
1142 mm.extendedPmMeChan <- meAttributes
1143 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001144 default:
1145 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001146 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001147 }
1148 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001149 return fmt.Errorf("unhandled-omci-get-response-message")
1150}
1151
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001152func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301153 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1154 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001155 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1156 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301157 }
1158 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1159 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001160 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1161 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301162 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001163 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 +05301164 if msgObj.Result == me.Success {
1165 meAttributes := msgObj.Attributes
1166 switch msgObj.EntityClass {
1167 case me.EthernetFrameExtendedPmClassID,
1168 me.EthernetFrameExtendedPm64BitClassID:
1169 mm.extendedPmMeChan <- meAttributes
1170 return nil
1171 default:
1172 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001173 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301174 }
1175 } else {
1176 meAttributes := msgObj.Attributes
1177 switch msgObj.EntityClass {
1178 case me.EthernetFrameExtendedPmClassID,
1179 me.EthernetFrameExtendedPm64BitClassID:
1180 // not all counters may be supported in which case we have seen some ONUs throwing
1181 // AttributeFailure error code, while correctly populating other counters it supports
1182 mm.extendedPmMeChan <- meAttributes
1183 return nil
1184 default:
1185 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001186 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301187 }
1188 }
1189 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1190}
1191
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001192func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001193 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1194 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001195 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1196 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 -08001197 }
1198 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1199 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001200 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1201 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 -08001202 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001203 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001204 if msgObj.Result == me.Success {
1205 switch msgObj.EntityClass {
1206 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001207 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001208 mm.syncTimeResponseChan <- true
1209 return nil
1210 default:
1211 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001212 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001213 }
1214 }
1215 mm.syncTimeResponseChan <- false
1216 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1217 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001218}
1219
Himani Chawlaee10b542021-09-20 16:46:40 +05301220func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1221 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1222 if msgLayer == nil {
1223 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1224 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1225 }
1226 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1227 if !msgOk {
1228 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1229 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1230 }
1231 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1232 switch msgObj.EntityClass {
1233 case me.EthernetFrameExtendedPmClassID,
1234 me.EthernetFrameExtendedPm64BitClassID:
1235 mm.extendedPMMeResponseChan <- msgObj.Result
1236 return nil
1237 default:
1238 logger.Errorw(ctx, "unhandled omci set response message",
1239 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1240 }
1241 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1242}
1243
Girish Gowdrae09a6202021-01-12 18:10:59 -08001244// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001245func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001246 // flush commMetricsChan
1247 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001248 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001249 logger.Debug(ctx, "flushed common metrics channel")
1250 default:
1251 }
1252
1253 // flush opticalMetricsChan
1254 select {
1255 case <-mm.opticalMetricsChan:
1256 logger.Debug(ctx, "flushed optical metrics channel")
1257 default:
1258 }
1259
1260 // flush uniStatusMetricsChan
1261 select {
1262 case <-mm.uniStatusMetricsChan:
1263 logger.Debug(ctx, "flushed uni status metrics channel")
1264 default:
1265 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001266
1267 // flush syncTimeResponseChan
1268 select {
1269 case <-mm.syncTimeResponseChan:
1270 logger.Debug(ctx, "flushed sync time response channel")
1271 default:
1272 }
1273
1274 // flush l2PmChan
1275 select {
1276 case <-mm.l2PmChan:
1277 logger.Debug(ctx, "flushed L2 PM collection channel")
1278 default:
1279 }
1280
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001281 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001282 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001283 case <-mm.StopTicks:
1284 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001285 default:
1286 }
1287
1288}
1289
1290// ** L2 PM FSM Handlers start **
1291
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001292func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001293
Girish Gowdrae0140f02021-02-02 16:55:09 -08001294 // Loop through all the group metrics
1295 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1296 // list of active L2 PM list then mark it for creation
1297 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1298 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001299 mm.OnuMetricsManagerLock.Lock()
1300 for n, g := range mm.GroupMetricMap {
1301 if g.IsL2PMCounter { // it is a l2 pm counter
1302 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001303 found := false
1304 inner1:
1305 for _, v := range mm.activeL2Pms {
1306 if v == n {
1307 found = true // metric already present in active l2 pm list
1308 break inner1
1309 }
1310 }
1311 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001312 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001313 }
1314 } else { // metric not enabled.
1315 found := false
1316 inner2:
1317 for _, v := range mm.activeL2Pms {
1318 if v == n {
1319 found = true // metric is found in active l2 pm list
1320 break inner2
1321 }
1322 }
1323 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001324 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001325 }
1326 }
1327 }
1328 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001329 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001330 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001331 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001332 go func() {
1333 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001334 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1335 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001336 }
1337 }()
1338}
1339
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001340func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001341 // Sync time with the ONU to establish 15min boundary for PM collection.
1342 if err := mm.syncTime(ctx); err != nil {
1343 go func() {
1344 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1345 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001346 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1347 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001348 }
1349 }()
1350 }
1351 // Initiate a tick generation routine every L2PmCollectionInterval
1352 go mm.generateTicks(ctx)
1353
1354 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001355 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1356 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001357 }
1358 }()
1359}
1360
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001361func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001362 // 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 +00001363 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001364 mm.activeL2Pms = nil
1365 mm.l2PmToAdd = nil
1366 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001367 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001368 // If the FSM was stopped, then clear PM data from KV store
1369 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001370 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001371 _ = mm.clearPmGroupData(ctx) // ignore error
1372 }
1373
Girish Gowdrae0140f02021-02-02 16:55:09 -08001374}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001375func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1376 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001377
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001378 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001379 numOfPmToDelete := len(mm.l2PmToDelete)
1380 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001381 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001382
1383 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001384 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 -08001385 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001386 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1387 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001388 }
1389 }()
1390 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001391 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 -08001392 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001393 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1394 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001395 }
1396 }()
1397 }
1398}
1399
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001400func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1401 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001402 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001403 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001404 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1405 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001406 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001407
1408 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001409 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001410
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001411 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1412 mm.OnuMetricsManagerLock.RLock()
1413 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1414 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1415 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001416
Girish Gowdrae0140f02021-02-02 16:55:09 -08001417 switch n {
1418 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001419 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001420 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001421 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1422 metricInfoSlice = append(metricInfoSlice, metricInfo)
1423 }
1424 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1425 metricInfoSlice = append(metricInfoSlice, metricInfo)
1426 }
1427 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001428 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001429 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001430 for _, entityID := range copyOfEntityIDs {
1431 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1432 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001433 }
1434 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001435
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001436 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001437 for _, entityID := range copyOfEntityIDs {
1438 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001439 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001440 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001441 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001442 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001443 for _, entityID := range copyOfEntityIDs {
1444 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001445 metricInfoSlice = append(metricInfoSlice, metricInfo)
1446 }
1447 }
1448
Girish Gowdrae0140f02021-02-02 16:55:09 -08001449 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001450 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001451 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001452 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001453 }
1454 // Does not matter we send success or failure here.
1455 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1456 // we have not exceed max attempts to collect the PM data)
1457 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001458 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1459 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001460 }
1461 }()
1462}
1463
Girish Gowdra0e533642021-03-02 22:02:51 -08001464// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001465func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001466 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001467 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001468 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1469 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001470 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001471
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001472 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001473 for _, n := range copyOfL2PmToAdd {
1474 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001475 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1476 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001477 switch n {
1478 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001479 // 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 +05301480 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001481 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001482 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001483 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001484 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1485 inner1:
1486 // retry L2PmCreateAttempts times to create the instance of PM
1487 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001488 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1489 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001490 if err != nil {
1491 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001492 log.Fields{"device-id": mm.deviceID})
1493 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001494 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001495 go func(p_pmFsm *cmn.AdapterFsm) {
1496 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001497 }(pPMFsm)
1498 }
1499 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001500 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001501 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001502 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1503 atLeastOneSuccess = true
1504 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1505 break inner1
1506 }
1507 }
1508 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1509 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001510 }
1511 }
1512 }
1513 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001514 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1515 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001516 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001517 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001518 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1519 inner2:
1520 // retry L2PmCreateAttempts times to create the instance of PM
1521 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001522 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1523 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001524 if err != nil {
1525 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001526 log.Fields{"device-id": mm.deviceID})
1527 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001528 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001529 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001530 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001531 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1532 atLeastOneSuccess = true
1533 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1534 break inner2
1535 }
1536 }
1537 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1538 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001539 }
1540 }
1541 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001542 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001543 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001544 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001545 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1546 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001547 if err != nil {
1548 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001549 log.Fields{"device-id": mm.deviceID})
1550 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001551 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001552 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001553 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001554 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1555 inner3:
1556 // retry L2PmCreateAttempts times to create the instance of PM
1557 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1558 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1559 atLeastOneSuccess = true
1560 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1561 break inner3
1562 }
1563 }
1564 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1565 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001566 }
1567 }
1568 case GemPortHistoryName:
1569
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001570 mm.OnuMetricsManagerLock.RLock()
1571 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1572 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1573 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001574
1575 if len(copyOfGemPortInstIDsToAdd) == 0 {
1576 // If there are no gemport history MEs to be created, just skip further processing
1577 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1578 // 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 +00001579 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001580 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001581 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001582 continue
1583 }
1584
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001585 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001586 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1587 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001588 if err != nil {
1589 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001590 log.Fields{"device-id": mm.deviceID})
1591 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001592 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001593 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001594 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001595 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1596 inner4:
1597 // retry L2PmCreateAttempts times to create the instance of PM
1598 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1599 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1600 atLeastOneSuccess = true
1601 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1602 break inner4
1603 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001604 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001605 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1606 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1607 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001608 }
1609
Girish Gowdrae0140f02021-02-02 16:55:09 -08001610 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001611 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001612 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001613 // 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
1614 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001615 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001616 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001617 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1618 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001619 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001620 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1621 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001622 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 +00001623 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001624 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001625 // 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 -08001626 // 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 +00001627 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001628 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001629 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001630 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001631
Girish Gowdrae0140f02021-02-02 16:55:09 -08001632 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001633 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001634 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001635 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001636 }
1637 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001638 mm.OnuMetricsManagerLock.RLock()
1639 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1640 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001641 // Does not matter we send success or failure here.
1642 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1643 // we have not exceed max attempts to create the PM ME)
1644 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001645 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1646 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001647 }
1648 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001649 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001650}
1651
Girish Gowdra0e533642021-03-02 22:02:51 -08001652// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001653func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001654 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001655 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001656 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1657 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001658 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001659
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001660 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001661 for _, n := range copyOfL2PmToDelete {
1662 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001663 cnt := 0
1664 atLeastOneDeleteFailure := false
1665
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001666 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1667 mm.OnuMetricsManagerLock.RLock()
1668 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1669 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1670 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001671
1672 if len(copyOfEntityIDs) == 0 {
1673 // 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 +00001674 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001675 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1676 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1677 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 +00001678 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001679 continue
1680 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001681 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001682 switch n {
1683 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001684 // 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 +05301685 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001686 for _, entityID := range copyOfEntityIDs {
1687 inner1:
1688 // retry L2PmDeleteAttempts times to delete the instance of PM
1689 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001690 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1691 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001692 if err != nil {
1693 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001694 log.Fields{"device-id": mm.deviceID})
1695 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001696 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001697 go func(p_pmFsm *cmn.AdapterFsm) {
1698 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001699 }(pPMFsm)
1700 }
1701 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001702 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001703 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001704 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1705 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
1706 atLeastOneDeleteFailure = true
1707 } else {
1708 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1709 break inner1
1710 }
1711 }
1712 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1713 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001714 }
1715 }
1716 }
1717 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001718 for _, entityID := range copyOfEntityIDs {
1719 inner2:
1720 // retry L2PmDeleteAttempts times to delete the instance of PM
1721 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001722 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1723 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001724 if err != nil {
1725 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001726 log.Fields{"device-id": mm.deviceID})
1727 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001728 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001729 go func(p_pmFsm *cmn.AdapterFsm) {
1730 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001731 }(pmFsm)
1732 return err
1733 }
1734 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001735 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001736 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001737 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdra0e533642021-03-02 22:02:51 -08001738 atLeastOneDeleteFailure = true
1739 } else {
1740 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001741 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001742 }
1743 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001744 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1745 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1746 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001747 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001748 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001749 for _, entityID := range copyOfEntityIDs {
1750 inner3:
1751 // retry L2PmDeleteAttempts times to delete the instance of PM
1752 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001753 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1754 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001755 if err != nil {
1756 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001757 log.Fields{"device-id": mm.deviceID})
1758 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001759 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001760 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001761 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001762 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
1763 atLeastOneDeleteFailure = true
1764 } else {
1765 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1766 break inner3
1767 }
1768 }
1769 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1770 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001771 }
1772 }
1773 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001774 for _, entityID := range copyOfEntityIDs {
1775 inner4:
1776 // retry L2PmDeleteAttempts times to delete the instance of PM
1777 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001778 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1779 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001780 if err != nil {
1781 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001782 log.Fields{"device-id": mm.deviceID})
1783 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001784 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001785 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001786 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001787 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
1788 atLeastOneDeleteFailure = true
1789 } else {
1790 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1791 break inner4
1792 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001793 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001794 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1795 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1796 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001797 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001798 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001799 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001800 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001801 // If we could not completely clean up the PM ME then just give up.
1802 if atLeastOneDeleteFailure {
1803 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001804 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001805 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001806 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001807 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1808 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1809 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001810 mm.GroupMetricMap[n].Enabled = false
1811 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001812 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001813 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001814 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001815 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1816 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001817 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001818 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1819 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001820 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 +00001821 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001822 }
1823 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001824 mm.OnuMetricsManagerLock.RLock()
1825 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1826 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001827 // Does not matter we send success or failure here.
1828 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1829 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001830 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1831 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001832 }
1833 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001834 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001835}
1836
1837// ** L2 PM FSM Handlers end **
1838
1839// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001840func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
1841 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1842 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001843 return err
1844 }
1845
1846 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001847 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1848 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1849 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001850 case syncTimeRes := <-mm.syncTimeResponseChan:
1851 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001852 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001853 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001854 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001855 return nil
1856 }
1857}
1858
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001859func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001860 var mEnt *me.ManagedEntity
1861 var omciErr me.OmciErrors
1862 var classID me.ClassID
1863 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001864 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001865 meParam := me.ParamData{EntityID: entityID}
1866 if upstream {
1867 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001868 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001869 return nil
1870 }
1871 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1872 } else {
1873 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001874 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001875 return nil
1876 }
1877 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1878 }
1879
Girish Gowdrae0140f02021-02-02 16:55:09 -08001880 intervalEndTime := -1
1881 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001882 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1883 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001884 }
1885
1886 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1887 ethPMHistData["class_id"] = float32(classID)
1888 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1889 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1890 ethPMHistData["parent_entity_id"] = float32(entityID)
1891 if upstream {
1892 ethPMHistData["upstream"] = float32(1)
1893 } else {
1894 ethPMHistData["upstream"] = float32(0)
1895 }
1896
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001897 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001898
Girish Gowdrae0140f02021-02-02 16:55:09 -08001899 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001900 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001901 return &metricInfo
1902}
1903
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001904func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001905 var mEnt *me.ManagedEntity
1906 var omciErr me.OmciErrors
1907 var classID me.ClassID
1908 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001909 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001910 meParam := me.ParamData{EntityID: entityID}
1911 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001912 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001913 return nil
1914 }
1915 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
1916
Girish Gowdrae0140f02021-02-02 16:55:09 -08001917 intervalEndTime := -1
1918 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001919 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
1920 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001921 }
1922
1923 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1924 ethUniHistData["class_id"] = float32(classID)
1925 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
1926
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001927 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001928
Girish Gowdrae0140f02021-02-02 16:55:09 -08001929 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001930 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001931 return &metricInfo
1932}
1933
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001934func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001935 var mEnt *me.ManagedEntity
1936 var omciErr me.OmciErrors
1937 var classID me.ClassID
1938 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001939 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001940 meParam := me.ParamData{EntityID: entityID}
1941 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001942 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001943 return nil
1944 }
1945 classID = me.FecPerformanceMonitoringHistoryDataClassID
1946
1947 intervalEndTime := -1
1948 fecHistData := make(map[string]float32)
1949 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
1950 return nil
1951 }
1952
1953 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1954 fecHistData["class_id"] = float32(classID)
1955 fecHistData["interval_end_time"] = float32(intervalEndTime)
1956
1957 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
1958
1959 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001960 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001961 return &metricInfo
1962}
1963
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001964func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001965 var mEnt *me.ManagedEntity
1966 var omciErr me.OmciErrors
1967 var classID me.ClassID
1968 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001969 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001970 meParam := me.ParamData{EntityID: entityID}
1971 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001972 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001973 return nil
1974 }
1975 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
1976
1977 intervalEndTime := -1
1978 gemHistData := make(map[string]float32)
1979 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
1980 return nil
1981 }
1982
1983 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
1984 gemHistData["class_id"] = float32(classID)
1985 gemHistData["interval_end_time"] = float32(intervalEndTime)
1986
1987 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
1988
1989 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001990 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001991 return &metricInfo
1992}
1993
Girish Gowdrae0140f02021-02-02 16:55:09 -08001994// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001995func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08001996 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001997 upstream := false
1998 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
1999 upstream = true
2000 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002001 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
2002 requestedAttributes["IntervalEndTime"] = 0
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002003 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002004 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002005 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2006 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002007 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002008 go func(p_pmFsm *cmn.AdapterFsm) {
2009 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002010 }(pmFsm)
2011 return err
2012 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002013 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002014 }
2015 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002016 select {
2017 case meAttributes = <-mm.l2PmChan:
2018 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002019 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2020 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002021 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002022 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002023 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002024 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002025 }
2026 // 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 -08002027 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002028 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002029 }
2030 }
2031 for k := range EthernetBridgeHistory {
2032 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2033 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2034 if _, ok := ethPMHistData[k]; !ok {
2035 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002036 case "entity_id":
2037 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2038 ethPMHistData[k] = float32(val.(uint16))
2039 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002040 case "drop_events":
2041 if val, ok := meAttributes["DropEvents"]; ok && val != nil {
2042 ethPMHistData[k] = float32(val.(uint32))
2043 }
2044 case "octets":
2045 if val, ok := meAttributes["Octets"]; ok && val != nil {
2046 ethPMHistData[k] = float32(val.(uint32))
2047 }
2048 case "packets":
2049 if val, ok := meAttributes["Packets"]; ok && val != nil {
2050 ethPMHistData[k] = float32(val.(uint32))
2051 }
2052 case "broadcast_packets":
2053 if val, ok := meAttributes["BroadcastPackets"]; ok && val != nil {
2054 ethPMHistData[k] = float32(val.(uint32))
2055 }
2056 case "multicast_packets":
2057 if val, ok := meAttributes["MulticastPackets"]; ok && val != nil {
2058 ethPMHistData[k] = float32(val.(uint32))
2059 }
2060 case "crc_errored_packets":
2061 if val, ok := meAttributes["CrcErroredPackets"]; ok && val != nil {
2062 ethPMHistData[k] = float32(val.(uint32))
2063 }
2064 case "undersize_packets":
2065 if val, ok := meAttributes["UndersizePackets"]; ok && val != nil {
2066 ethPMHistData[k] = float32(val.(uint32))
2067 }
2068 case "oversize_packets":
2069 if val, ok := meAttributes["OversizePackets"]; ok && val != nil {
2070 ethPMHistData[k] = float32(val.(uint32))
2071 }
2072 case "64_octets":
2073 if val, ok := meAttributes["Packets64Octets"]; ok && val != nil {
2074 ethPMHistData[k] = float32(val.(uint32))
2075 }
2076 case "65_to_127_octets":
2077 if val, ok := meAttributes["Packets65To127Octets"]; ok && val != nil {
2078 ethPMHistData[k] = float32(val.(uint32))
2079 }
2080 case "128_to_255_octets":
2081 if val, ok := meAttributes["Packets128To255Octets"]; ok && val != nil {
2082 ethPMHistData[k] = float32(val.(uint32))
2083 }
2084 case "256_to_511_octets":
2085 if val, ok := meAttributes["Packets256To511Octets"]; ok && val != nil {
2086 ethPMHistData[k] = float32(val.(uint32))
2087 }
2088 case "512_to_1023_octets":
2089 if val, ok := meAttributes["Packets512To1023Octets"]; ok && val != nil {
2090 ethPMHistData[k] = float32(val.(uint32))
2091 }
2092 case "1024_to_1518_octets":
2093 if val, ok := meAttributes["Packets1024To1518Octets"]; ok && val != nil {
2094 ethPMHistData[k] = float32(val.(uint32))
2095 }
2096 default:
2097 // do nothing
2098 }
2099 }
2100 }
2101 return nil
2102}
2103
2104// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002105func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002106 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002107 // 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 +03002108 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2109 requestedAttributes["IntervalEndTime"] = 0
2110 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002111 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002112 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002113 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2114 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2115 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002116 }
2117 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002118 select {
2119 case meAttributes = <-mm.l2PmChan:
2120 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002121 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2122 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002123 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002124 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002125 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002126 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002127 }
2128 // 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 -08002129 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002130 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002131 }
2132 }
2133 for k := range EthernetUniHistory {
2134 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2135 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2136 if _, ok := ethPMUniHistData[k]; !ok {
2137 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002138 case "entity_id":
2139 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2140 ethPMUniHistData[k] = float32(val.(uint16))
2141 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002142 case "fcs_errors":
2143 if val, ok := meAttributes["FcsErrors"]; ok && val != nil {
2144 ethPMUniHistData[k] = float32(val.(uint32))
2145 }
2146 case "excessive_collision_counter":
2147 if val, ok := meAttributes["ExcessiveCollisionCounter"]; ok && val != nil {
2148 ethPMUniHistData[k] = float32(val.(uint32))
2149 }
2150 case "late_collision_counter":
2151 if val, ok := meAttributes["LateCollisionCounter"]; ok && val != nil {
2152 ethPMUniHistData[k] = float32(val.(uint32))
2153 }
2154 case "frames_too_long":
2155 if val, ok := meAttributes["FramesTooLong"]; ok && val != nil {
2156 ethPMUniHistData[k] = float32(val.(uint32))
2157 }
2158 case "buffer_overflows_on_rx":
2159 if val, ok := meAttributes["BufferOverflowsOnReceive"]; ok && val != nil {
2160 ethPMUniHistData[k] = float32(val.(uint32))
2161 }
2162 case "buffer_overflows_on_tx":
2163 if val, ok := meAttributes["BufferOverflowsOnTransmit"]; ok && val != nil {
2164 ethPMUniHistData[k] = float32(val.(uint32))
2165 }
2166 case "single_collision_frame_counter":
2167 if val, ok := meAttributes["SingleCollisionFrameCounter"]; ok && val != nil {
2168 ethPMUniHistData[k] = float32(val.(uint32))
2169 }
2170 case "multiple_collisions_frame_counter":
2171 if val, ok := meAttributes["MultipleCollisionsFrameCounter"]; ok && val != nil {
2172 ethPMUniHistData[k] = float32(val.(uint32))
2173 }
2174 case "sqe_counter":
2175 if val, ok := meAttributes["SqeCounter"]; ok && val != nil {
2176 ethPMUniHistData[k] = float32(val.(uint32))
2177 }
2178 case "deferred_tx_counter":
2179 if val, ok := meAttributes["DeferredTransmissionCounter"]; ok && val != nil {
2180 ethPMUniHistData[k] = float32(val.(uint32))
2181 }
2182 case "internal_mac_tx_error_counter":
2183 if val, ok := meAttributes["InternalMacTransmitErrorCounter"]; ok && val != nil {
2184 ethPMUniHistData[k] = float32(val.(uint32))
2185 }
2186 case "carrier_sense_error_counter":
2187 if val, ok := meAttributes["CarrierSenseErrorCounter"]; ok && val != nil {
2188 ethPMUniHistData[k] = float32(val.(uint32))
2189 }
2190 case "alignment_error_counter":
2191 if val, ok := meAttributes["AlignmentErrorCounter"]; ok && val != nil {
2192 ethPMUniHistData[k] = float32(val.(uint32))
2193 }
2194 case "internal_mac_rx_error_counter":
2195 if val, ok := meAttributes["InternalMacReceiveErrorCounter"]; ok && val != nil {
2196 ethPMUniHistData[k] = float32(val.(uint32))
2197 }
2198 default:
2199 // do nothing
2200 }
2201 }
2202 }
2203 return nil
2204}
2205
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002206// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002207func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002208 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002209 // 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 +03002210 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2211 requestedAttributes["IntervalEndTime"] = 0
2212 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002213 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002214 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002215 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2216 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2217 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002218 }
2219 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002220 select {
2221 case meAttributes = <-mm.l2PmChan:
2222 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002223 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2224 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002225 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002226 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002227 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002228 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002229 }
2230 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2231 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002232 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002233 }
2234 }
2235 for k := range FecHistory {
2236 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2237 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2238 if _, ok := fecHistData[k]; !ok {
2239 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002240 case "entity_id":
2241 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2242 fecHistData[k] = float32(val.(uint16))
2243 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002244 case "corrected_bytes":
2245 if val, ok := meAttributes["CorrectedBytes"]; ok && val != nil {
2246 fecHistData[k] = float32(val.(uint32))
2247 }
2248 case "corrected_code_words":
2249 if val, ok := meAttributes["CorrectedCodeWords"]; ok && val != nil {
2250 fecHistData[k] = float32(val.(uint32))
2251 }
2252 case "uncorrectable_code_words":
2253 if val, ok := meAttributes["UncorrectableCodeWords"]; ok && val != nil {
2254 fecHistData[k] = float32(val.(uint32))
2255 }
2256 case "total_code_words":
2257 if val, ok := meAttributes["TotalCodeWords"]; ok && val != nil {
2258 fecHistData[k] = float32(val.(uint32))
2259 }
2260 case "fec_seconds":
2261 if val, ok := meAttributes["FecSeconds"]; ok && val != nil {
2262 fecHistData[k] = float32(val.(uint16))
2263 }
2264 default:
2265 // do nothing
2266 }
2267 }
2268 }
2269 return nil
2270}
2271
2272// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002273func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002274 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002275 // Insert "IntervalEndTime" is 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 +03002276 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2277 requestedAttributes["IntervalEndTime"] = 0
2278 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002279 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002280 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002281 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2282 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2283 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002284 }
2285 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002286 select {
2287 case meAttributes = <-mm.l2PmChan:
2288 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002289 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2290 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002291 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002292 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002293 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002294 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002295 }
2296 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2297 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002298 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002299 }
2300 }
2301 for k := range GemPortHistory {
2302 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2303 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2304 if _, ok := gemPortHistData[k]; !ok {
2305 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002306 case "entity_id":
2307 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2308 gemPortHistData[k] = float32(val.(uint16))
2309 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002310 case "transmitted_gem_frames":
2311 if val, ok := meAttributes["TransmittedGemFrames"]; ok && val != nil {
2312 gemPortHistData[k] = float32(val.(uint32))
2313 }
2314 case "received_gem_frames":
2315 if val, ok := meAttributes["ReceivedGemFrames"]; ok && val != nil {
2316 gemPortHistData[k] = float32(val.(uint32))
2317 }
2318 case "received_payload_bytes":
2319 if val, ok := meAttributes["ReceivedPayloadBytes"]; ok && val != nil {
2320 gemPortHistData[k] = float32(val.(uint64))
2321 }
2322 case "transmitted_payload_bytes":
2323 if val, ok := meAttributes["TransmittedPayloadBytes"]; ok && val != nil {
2324 gemPortHistData[k] = float32(val.(uint64))
2325 }
2326 case "encryption_key_errors":
2327 if val, ok := meAttributes["EncryptionKeyErrors"]; ok && val != nil {
2328 gemPortHistData[k] = float32(val.(uint32))
2329 }
2330 default:
2331 // do nothing
2332 }
2333 }
2334 }
2335 return nil
2336}
2337
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002338func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002339 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2340 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002341 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2342 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 -08002343 }
2344 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2345 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002346 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2347 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 -08002348 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002349 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002350 switch msgObj.EntityClass {
2351 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2352 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002353 me.EthernetPerformanceMonitoringHistoryDataClassID,
2354 me.FecPerformanceMonitoringHistoryDataClassID,
2355 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002356 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2357 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2358 mm.l2PmCreateOrDeleteResponseChan <- true
2359 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002360 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002361 mm.l2PmCreateOrDeleteResponseChan <- false
2362 }
2363 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302364 case me.EthernetFrameExtendedPmClassID,
2365 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302366 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302367 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002368 default:
2369 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002370 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002371 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002372 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002373}
2374
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002375func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002376 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2377 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002378 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2379 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 -08002380 }
2381 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2382 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002383 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2384 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 -08002385 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002386 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002387 switch msgObj.EntityClass {
2388 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2389 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002390 me.EthernetPerformanceMonitoringHistoryDataClassID,
2391 me.FecPerformanceMonitoringHistoryDataClassID,
2392 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002393 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2394 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2395 mm.l2PmCreateOrDeleteResponseChan <- true
2396 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002397 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002398 mm.l2PmCreateOrDeleteResponseChan <- false
2399 }
2400 return nil
2401 default:
2402 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002403 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002404 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002405 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002406}
2407
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002408func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002409 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002410 for {
2411 select {
2412 case <-time.After(L2PmCollectionInterval * time.Second):
2413 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002414 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2415 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002416 }
2417 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002418 case <-mm.StopTicks:
2419 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002420 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002421 return
2422 }
2423 }
2424}
2425
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002426func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002427 // Publish metrics if it is valid
2428 if metricInfoSlice != nil {
2429 mm.publishMetrics(ctx, metricInfoSlice)
2430 } else {
2431 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2432 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002433 mm.OnuMetricsManagerLock.Lock()
2434 mm.GroupMetricMap[metricName].collectAttempts++
2435 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002436 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2437 }
2438 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002439 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2440 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002441 }
2442}
2443
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002444func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002445 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2446 var grpFunc groupMetricPopulateFunc
2447 switch classID {
2448 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2449 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2450 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2451 grpFunc = mm.populateEthernetUniHistoryMetrics
2452 case me.FecPerformanceMonitoringHistoryDataClassID:
2453 grpFunc = mm.populateFecHistoryMetrics
2454 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2455 grpFunc = mm.populateGemPortMetrics
2456 default:
2457 return fmt.Errorf("unknown-classid-%v", classID)
2458 }
2459
2460 size := 0
2461 requestedAttributes := make(me.AttributeValueMap)
2462 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002463 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2464 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2465 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2466 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2467 continue
2468 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002469 if (v.Size + size) <= MaxL2PMGetPayLoadSize {
2470 requestedAttributes[v.Name] = v.DefValue
2471 size = v.Size + size
2472 } else { // We exceeded the allow omci get size
2473 // Let's collect the attributes via get now and collect remaining in the next iteration
2474 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2475 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002476 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002477 return err
2478 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002479 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002480 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2481 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002482 }
2483 }
2484 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002485 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2486 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002487 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002488 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002489 }
2490 return nil
2491}
2492
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002493func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002494 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002495 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2496 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2497 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002498
2499 raisedTs := time.Now().Unix()
2500 mmd := voltha.MetricMetaData{
2501 Title: title,
2502 Ts: float64(raisedTs),
2503 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002504 DeviceId: mm.deviceID,
2505 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2506 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002507 }
2508
2509 // create slice of metrics given that there could be more than one VEIP instance
2510 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2511 return metricInfo
2512}
2513
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002514func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002515 valid := false
2516 if *intervalEndTime == -1 { // first time
2517 // Update the interval end time
2518 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2519 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2520 valid = true
2521 }
2522 } else {
2523 var currIntervalEndTime int
2524 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2525 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2526 }
2527 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2528 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002529 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002530 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2531 } else {
2532 valid = true
2533 }
2534 }
2535 return valid
2536}
2537
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002538func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002539 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
2540 select {
2541 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002542 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002543 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002544 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002545 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002546 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002547 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002548 }
2549 return false
2550}
2551
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002552func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002553 var pmConfigSlice []*voltha.PmConfig
2554 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002555 pmConfigSlice = append(pmConfigSlice,
2556 &voltha.PmConfig{
2557 Name: k,
2558 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002559 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002560 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002561 }
2562 groupMetric := voltha.PmGroupConfig{
2563 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002564 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002565 GroupFreq: grpFreq,
2566 Metrics: pmConfigSlice,
2567 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002568 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002569
2570}
2571
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002572func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2573 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2574 if mm.PAdaptFsm == nil {
2575 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2576 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002577 return fmt.Errorf("nil-adapter-fsm")
2578 }
2579 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002580 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2581 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002582 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002583 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2584 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2585 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2586 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2587 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2588 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2589 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2590 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2591 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002592 },
2593 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002594 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2595 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2596 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2597 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2598 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2599 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2600 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2601 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002602 },
2603 )
2604 return nil
2605}
2606
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002607func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2608 mm.pDeviceHandler.InitPmConfigs()
2609 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2610 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2611 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2612 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002613
2614 // Populate group metrics.
2615 // Lets populate irrespective of GroupMetricEnabled is true or not.
2616 // The group metrics collection will decided on this flag later
2617
2618 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2619 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2620
2621 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2622 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2623
2624 // classical l2 pm counter start
2625
2626 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2627 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2628
2629 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2630 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2631
2632 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2633 FecHistoryEnabled, FecHistoryFrequency)
2634
2635 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2636 GemPortHistoryEnabled, GemPortHistoryFrequency)
2637
2638 // classical l2 pm counter end
2639
2640 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2641}
2642
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002643func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002644 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2646 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002647 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002648 Enabled: g.Enabled,
2649 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002650 }
2651 switch g.GroupName {
2652 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002653 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002654 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002655 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002656 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002657 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2658 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002659 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2661 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002662 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002663 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2664 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002665 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002666 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2667 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002668 default:
2669 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"groupName": g.GroupName})
2670 }
2671 }
2672
2673 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002674 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2675 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002676 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002677 Enabled: m.Enabled,
2678 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002679 }
2680 switch m.Name {
2681 // None exist as of now. Add when available.
2682 default:
2683 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"metricName": m.Name})
2684 }
2685 }
2686}
2687
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002688// AddGemPortForPerfMonitoring - TODO: add comment
2689func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2690 mm.OnuMetricsManagerLock.Lock()
2691 defer mm.OnuMetricsManagerLock.Unlock()
2692 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002693 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002694 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002695 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002696 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002697
2698 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2699 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2700 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2701 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2702 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002703
2704 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002705 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2706 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002707 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002708 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002709 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002710 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002711 }
2712 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002713}
2714
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002715// RemoveGemPortForPerfMonitoring - TODO: add comment
2716func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2717 mm.OnuMetricsManagerLock.Lock()
2718 defer mm.OnuMetricsManagerLock.Unlock()
2719 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2720 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002721 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002722 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002723
2724 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2725 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2726 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2727 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2728 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002729
2730 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002731 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2732 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002733 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002734 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002735 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002736 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002737 }
2738 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002739}
2740
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002741func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2742 if mm.pDeviceHandler.GetOnuTP() != nil {
2743 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002744 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002745 for _, v := range gemPortInstIDs {
2746 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002747 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002748 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002749 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002750 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002751 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002752 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002753 }
2754}
2755
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002756func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2757 if mm.pDeviceHandler.GetOnuTP() != nil {
2758 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002759 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002760 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002761 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002762 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002763 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002764 }
2765 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002766 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002767 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002768}
2769
2770// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002771func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2772 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002773 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002774 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2775 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002776 }
2777 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002778 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002779 group.pmMEData = &pmMEData{}
2780 Value, err := mm.pmKvStore.Get(ctx, groupName)
2781 if err == nil {
2782 if Value != nil {
2783 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002784 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002785 tmpBytes, _ := kvstore.ToByte(Value.Value)
2786
2787 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002788 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2789 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 -08002790 continue
2791 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002792 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002793 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002794 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002795 continue
2796 }
2797 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002798 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2799 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 -08002800 continue
2801 }
2802 }
2803 if len(errorsList) > 0 {
2804 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2805 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002806 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002807 return nil
2808}
2809
2810// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2811// the data must be available in cache.
2812// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002813func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2814 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002815 return grp.pmMEData, nil
2816 }
2817 // Data not in cache, try to fetch from kv store.
2818 data := &pmMEData{}
2819 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002820 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2821 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002822 }
2823 Value, err := mm.pmKvStore.Get(ctx, groupName)
2824 if err == nil {
2825 if Value != nil {
2826 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002827 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002828 tmpBytes, _ := kvstore.ToByte(Value.Value)
2829
2830 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002831 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002832 return data, err
2833 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002834 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002835 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002836 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002837 return data, err
2838 }
2839 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002840 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002841 return data, err
2842 }
2843
2844 return data, nil
2845}
2846
2847// 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 +00002848func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2849 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2850 mm.OnuMetricsManagerLock.Lock()
2851 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002852
2853 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002854 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2855 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002856 }
2857
2858 pmMEData, err := mm.getPmData(ctx, groupName)
2859 if err != nil || pmMEData == nil {
2860 // error already logged in called function.
2861 return err
2862 }
2863 switch pmAction {
2864 case cPmAdd:
2865 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2866 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2867 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2868 case cPmAdded:
2869 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2870 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2871 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2872 case cPmRemove:
2873 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2874 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2875 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2876 case cPmRemoved:
2877 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2878 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2879 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2880 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002881 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2882 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 -08002883 }
2884 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002885 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002886
2887 Value, err := json.Marshal(*pmMEData)
2888 if err != nil {
2889 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
2890 return err
2891 }
2892 // Update back to kv store
2893 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
2894 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
2895 return err
2896 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002897 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002898
2899 return nil
2900}
2901
2902// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002903func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2904 mm.OnuMetricsManagerLock.Lock()
2905 defer mm.OnuMetricsManagerLock.Unlock()
2906 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002907 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002908 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2909 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002910 }
2911
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002912 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002913 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002914 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002915 // do not abort this procedure. continue to delete next group.
2916 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002917 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002918 }
2919 }
2920
2921 return nil
2922}
2923
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002924// ClearAllPmData clears all PM data associated with the device from KV store
2925func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
2926 mm.OnuMetricsManagerLock.Lock()
2927 defer mm.OnuMetricsManagerLock.Unlock()
2928 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002929 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002930 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2931 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002932 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002933 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002934 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002935 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002936 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002937 value = err
2938 // do not abort this procedure - continue to delete next group.
2939 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002940 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002941 }
Girish Gowdra0e533642021-03-02 22:02:51 -08002942 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002943 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002944 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002945 }
2946 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002947}
2948
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002949func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
2950 mm.OnuMetricsManagerLock.Lock()
2951 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002952 mm.omciProcessingActive = status
2953}
2954
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002955// updateTickGenerationStatus - TODO: add comment
2956func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
2957 mm.OnuMetricsManagerLock.Lock()
2958 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002959 mm.tickGenerationActive = status
2960}
2961
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002962// GetOmciProcessingStatus - TODO: add comment
2963func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
2964 mm.OnuMetricsManagerLock.RLock()
2965 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002966 return mm.omciProcessingActive
2967}
2968
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002969// GetTickGenerationStatus - TODO: add comment
2970func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
2971 mm.OnuMetricsManagerLock.RLock()
2972 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002973 return mm.tickGenerationActive
2974}
2975
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002976func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002977 for _, ele := range slice {
2978 if ele == n {
2979 return slice
2980 }
2981 }
2982 return append(slice, n)
2983}
2984
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002985func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002986 for i, ele := range slice {
2987 if ele == n {
2988 return append(slice[:i], slice[i+1:]...)
2989 }
2990 }
2991 return slice
2992}
2993
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002994func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002995 for _, ele := range slice {
2996 if ele == n {
2997 return slice
2998 }
2999 }
3000 return append(slice, n)
3001}
3002
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003003func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003004 for i, ele := range slice {
3005 if ele == n {
3006 return append(slice[:i], slice[i+1:]...)
3007 }
3008 }
3009 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003010}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303011
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003012func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303013 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3014 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003015 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3016 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3017 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303018 Value, err := mm.extPmKvStore.Get(ctx, key)
3019 if err == nil {
3020 if Value != nil {
3021 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003022 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303023 tmpBytes, _ := kvstore.ToByte(Value.Value)
3024
3025 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003026 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303027 return false, err
3028 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003029 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303030 // We have found the data from db, no need to get through omci get message.
3031 mm.supportedEthernetFrameExtendedPMClass = data
3032 return true, nil
3033 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003034 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303035 return false, nil
3036 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003037 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303038 return false, err
3039}
3040
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003041func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303042 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
3043 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303044 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303045 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003046 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303047 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3048 if resp == me.Success || resp == me.InstanceExists {
3049 return true, nil
3050 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3051 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3052 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3053 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054 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 +05303055 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3056 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003057 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303058 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003059 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303060 }
3061 return false, fmt.Errorf("timeout-while-waiting-for-response")
3062}
3063
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003064func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303065 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303066 // 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 +05303067 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003068 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303069 var entityID uint16
3070 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003071 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303072 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003073 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303074 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303075 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303076 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303077 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303078
3079 inner1:
3080 // retry ExtendedPmCreateAttempts times to create the instance of PM
3081 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003082 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3083 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3084 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303085 if err != nil {
3086 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003087 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303088 return false, err
3089 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303090 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3091 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303092 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303093 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303094 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303095 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303096 }
3097 break inner1
3098 } else if err != nil {
3099 if !supported {
3100 // Need to return immediately
3101 return false, err
3102 }
3103 //In case of failure, go for a retry
3104 }
3105 }
3106 if cnt == ExtendedPmCreateAttempts {
3107 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3108 return true, fmt.Errorf("unable-to-create-me")
3109 }
3110 }
3111 }
3112 return true, nil
3113}
3114
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003115func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3116 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3117 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3118 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303119 // check if we get the supported type me for ethernet frame extended pm class id
3120 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3121 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3122 }
3123 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3124 if err != nil {
3125 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"err": err})
3126 }
3127 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
3128 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"err": err})
3129 }
3130}
3131
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003132func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303133 mm.onuEthernetFrameExtendedPmLock.Lock()
3134 mm.isDeviceReadyToCollectExtendedPmStats = true
3135 mm.onuEthernetFrameExtendedPmLock.Unlock()
3136}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003137
Himani Chawlaee10b542021-09-20 16:46:40 +05303138// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003139func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303140 //get the type of extended frame pm me supported by onu first
3141 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3142 if err != nil {
3143 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3144 return
3145 }
3146 if exist {
3147 // we have the me type, go ahead with the me type supported.
3148 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003149 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303150 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3151 return
3152 }
3153 mm.setAllExtPmMeCreatedFlag()
3154 return
3155 }
3156 // First try with 64 bit me
3157 // we have the me type, go ahead with the me type supported.
3158 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3159 if err != nil && !supported64Bit {
3160 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003161 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303162 "supported": supported64Bit})
3163 // Then Try with 32 bit type
3164 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003165 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303166 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3167 } else if supported32Bit {
3168 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3169 mm.putExtPmMeKvStore(ctx)
3170 mm.setAllExtPmMeCreatedFlag()
3171 }
3172 } else if err == nil && supported64Bit {
3173 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3174 mm.putExtPmMeKvStore(ctx)
3175 mm.setAllExtPmMeCreatedFlag()
3176 }
3177}
3178
Himani Chawlaee10b542021-09-20 16:46:40 +05303179func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3180 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3181 uniPortEntityID := entityID
3182 if upstream {
3183 uniPortEntityID = entityID - 0x100
3184 }
3185 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3186 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3187 mm.pDeviceHandler.GetOmciTimeout(), true,
3188 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3189 if err != nil {
3190 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3191 log.Fields{"device-id": mm.deviceID})
3192 return extension.GetValueResponse_INTERNAL_ERROR, err
3193 }
3194
3195 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3196 return extension.GetValueResponse_REASON_UNDEFINED, nil
3197 }
3198 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3199}
3200
3201func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3202 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
3203 select {
3204 case resp := <-mm.extendedPMMeResponseChan:
3205 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3206 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3207 if resp == me.Success {
3208 return true
3209 }
3210 return false
3211 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3212 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3213 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3214 }
3215 return false
3216}
3217
3218func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3219 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3220 className := "EthernetFrameExtendedPm64Bit"
3221 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3222 className = "EthernetFrameExtendedPm"
3223 }
3224 // Reset the counters if option is specified
3225 for entityID := range upstreamEntityMap {
3226 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3227 true)
3228 if err != nil {
3229 return errReason, err
3230 }
3231 }
3232
3233 for entityID := range downstreamEntityMap {
3234 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3235 true)
3236 if err != nil {
3237 return errReason, err
3238 }
3239 }
3240 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3241 // device itself.
3242 // Unset the reset bit if option is specified
3243 for entityID := range upstreamEntityMap {
3244 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3245 false)
3246 if err != nil {
3247 return errReason, err
3248 }
3249 }
3250
3251 for entityID := range downstreamEntityMap {
3252 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3253 false)
3254 if err != nil {
3255 return errReason, err
3256 }
3257 }
3258 return extension.GetValueResponse_REASON_UNDEFINED, nil
3259}
3260
3261func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3262 mm.onuEthernetFrameExtendedPmLock.Lock()
3263 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3264 mm.isEthernetFrameExtendedPmOperationOngoing = val
3265}
3266
3267func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3268 mm.onuEthernetFrameExtendedPmLock.Lock()
3269 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3270 return mm.isEthernetFrameExtendedPmOperationOngoing
3271}
3272
3273// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3274func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3275 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3276 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3277 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303278 return &extension.SingleGetValueResponse{
3279 Response: &extension.GetValueResponse{
3280 Status: extension.GetValueResponse_ERROR,
3281 ErrReason: reason,
3282 },
3283 }
3284 }
3285 mm.onuEthernetFrameExtendedPmLock.RLock()
3286 if !mm.isDeviceReadyToCollectExtendedPmStats {
3287 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303288 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303289 }
3290 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303291
3292 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3293 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3294 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3295 }
3296 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3297 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3298
3299 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3300 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3301 if onuInfo.IsUniIndex != nil {
3302 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3303 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3304 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3305 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3306 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3307 break
3308 }
3309 }
3310 if len(downstreamEntityMap) == 0 {
3311 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3312 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3313 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3314 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3315 }
3316 } else {
3317 // make a copy of all downstream and upstream maps in the local ones
3318 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3319 upstreamEntityMap[entityID] = meEnt
3320 }
3321 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3322 downstreamEntityMap[entityID] = meEnt
3323 }
3324 }
3325 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3326 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3327 // Reset the metrics first for all required me's
3328 if onuInfo.Reset_ {
3329 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3330 if err != nil {
3331 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3332 log.Fields{"device-id": mm.deviceID})
3333 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3334 }
3335 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303336 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3337 var pmUpstream extension.OmciEthernetFrameExtendedPm
3338 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303339 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3340 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3341 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3342 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303343 if !onuInfo.Reset_ {
3344 for entityID, meEnt := range upstreamEntityMap {
3345 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3346 var receivedMask uint16
3347 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3348 if receivedMask == 0 {
3349 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303350 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3351 // It might be possible that still some downstream pms are supported and hence we need to continue
3352 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3353 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303354 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303355 // Aggregate the result for upstream
3356 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3357 } else {
3358 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303359 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303360 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303361
Himani Chawlaee10b542021-09-20 16:46:40 +05303362 for entityID, meEnt := range downstreamEntityMap {
3363 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3364 var receivedMask uint16
3365 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303366 if receivedMask == 0 {
3367 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3368 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3369 // Stop collecting downstream counters for other ME's.
3370 break
3371 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303372 // Aggregate the result for downstream
3373 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3374 } else {
3375 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3376 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303377 }
3378 }
3379 singleValResp := extension.SingleGetValueResponse{
3380 Response: &extension.GetValueResponse{
3381 Status: extension.GetValueResponse_OK,
3382 Response: &extension.GetValueResponse_OnuCounters{
3383 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303384 Upstream: &pmUpstream,
3385 Downstream: &pmDownstream,
3386 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303387 },
3388 },
3389 },
3390 }
3391 return &singleValResp
3392}
3393
Himani Chawlaee10b542021-09-20 16:46:40 +05303394func (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 +05303395 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003396 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 +05303397
3398 classID = mm.supportedEthernetFrameExtendedPMClass
3399 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3400 if classID == me.EthernetFrameExtendedPmClassID {
3401 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3402 }
3403 ethPMData := make(map[string]uint64)
3404 var sumReceivedMask uint16
3405 for mask := range attributeMaskList {
3406 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3407 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003408 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303409 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303410 }
3411 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3412 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3413 //populate all counters as failure and return
3414 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3415 break
3416 }
3417 }
3418 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303419 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303420}
3421
3422// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003423func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303424 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3425 var meAttributes me.AttributeValueMap
3426 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003427 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303428 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003429 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303430 return extension.GetValueResponse_INTERNAL_ERROR, err
3431 }
3432 select {
3433 case meAttributes = <-mm.extendedPmMeChan:
3434 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003435 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3436 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303437 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003438 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303439 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3440 }
3441 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3442 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3443 *sumReceivedMask += mask
3444 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3445 } else {
3446 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3447 *sumReceivedMask += mask
3448 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3449 }
3450
3451 return extension.GetValueResponse_REASON_UNDEFINED, nil
3452}
3453
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003454func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303455 sourceMap := maskToEthernetFrameExtendedPM64Bit
3456 errorCounterValue := UnsupportedCounterValue64bit
3457 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3458 sourceMap = maskToEthernetFrameExtendedPM32Bit
3459 errorCounterValue = UnsupportedCounterValue32bit
3460 }
3461 for _, value := range sourceMap {
3462 for _, k := range value {
3463 if _, ok := ethFrameExtPMData[k]; !ok {
3464 ethFrameExtPMData[k] = errorCounterValue
3465 }
3466 }
3467 }
3468}
3469
3470// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003471func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303472 receivedMask := uint16(0)
3473 switch requestedAttributesMask {
3474 case 0x3F00:
3475 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3476 if _, ok := ethFrameExtPMData[k]; !ok {
3477 switch k {
3478 case "drop_events":
3479 if val, ok := meAttributes[dropEvents]; ok && val != nil {
3480 ethFrameExtPMData[k] = uint64(val.(uint32))
3481 receivedMask |= 0x2000
3482 } else if !ok {
3483 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3484 }
3485 case "octets":
3486 if val, ok := meAttributes[octets]; ok && val != nil {
3487 ethFrameExtPMData[k] = uint64(val.(uint32))
3488 receivedMask |= 0x1000
3489 } else if !ok {
3490 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3491 }
3492 case "frames":
3493 if val, ok := meAttributes[frames]; ok && val != nil {
3494 ethFrameExtPMData[k] = uint64(val.(uint32))
3495 receivedMask |= 0x800
3496 } else if !ok {
3497 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3498 }
3499 case "broadcast_frames":
3500 if val, ok := meAttributes[broadcastFrames]; ok && val != nil {
3501 ethFrameExtPMData[k] = uint64(val.(uint32))
3502 receivedMask |= 0x400
3503 } else if !ok {
3504 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3505 }
3506 case "multicast_frames":
3507 if val, ok := meAttributes[multicastFrames]; ok && val != nil {
3508 ethFrameExtPMData[k] = uint64(val.(uint32))
3509 receivedMask |= 0x200
3510 } else if !ok {
3511 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3512 }
3513 case "crc_errored_frames":
3514 if val, ok := meAttributes[crcErroredFrames]; ok && val != nil {
3515 ethFrameExtPMData[k] = uint64(val.(uint32))
3516 receivedMask |= 0x100
3517 } else if !ok {
3518 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3519 }
3520 default:
3521 //do nothing
3522 }
3523 }
3524 }
3525 case 0x00FC:
3526 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3527 if _, ok := ethFrameExtPMData[k]; !ok {
3528 switch k {
3529 case "undersize_frames":
3530 if val, ok := meAttributes[undersizeFrames]; ok && val != nil {
3531 ethFrameExtPMData[k] = uint64(val.(uint32))
3532 receivedMask |= 0x80
3533 } else if !ok {
3534 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3535 }
3536 case "oversize_frames":
3537 if val, ok := meAttributes[oversizeFrames]; ok && val != nil {
3538 ethFrameExtPMData[k] = uint64(val.(uint32))
3539 receivedMask |= 0x40
3540 } else if !ok {
3541 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3542 }
3543 case "64_octets":
3544 if val, ok := meAttributes[frames64Octets]; ok && val != nil {
3545 ethFrameExtPMData[k] = uint64(val.(uint32))
3546 receivedMask |= 0x20
3547 } else if !ok {
3548 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3549 }
3550 case "65_to_127_octets":
3551 if val, ok := meAttributes[frames65To127Octets]; ok && val != nil {
3552 ethFrameExtPMData[k] = uint64(val.(uint32))
3553 receivedMask |= 0x10
3554 } else if !ok {
3555 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3556 }
3557 case "128_to_255_octets":
3558 if val, ok := meAttributes[frames128To255Octets]; ok && val != nil {
3559 ethFrameExtPMData[k] = uint64(val.(uint32))
3560 receivedMask |= 0x8
3561 } else if !ok {
3562 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3563 }
3564 case "256_to_511_octets":
3565 if val, ok := meAttributes[frames256To511Octets]; ok && val != nil {
3566 ethFrameExtPMData[k] = uint64(val.(uint32))
3567 receivedMask |= 0x4
3568 } else if !ok {
3569 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3570 }
3571 default:
3572 //do nothing
3573 }
3574 }
3575 }
3576 case 0x0003:
3577 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3578 if _, ok := ethFrameExtPMData[k]; !ok {
3579 switch k {
3580 case "512_to_1023_octets":
3581 if val, ok := meAttributes[frames512To1023Octets]; ok && val != nil {
3582 ethFrameExtPMData[k] = uint64(val.(uint32))
3583 receivedMask |= 0x2
3584 } else if !ok {
3585 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3586 }
3587 case "1024_to_1518_octets":
3588 if val, ok := meAttributes[frames1024To1518Octets]; ok && val != nil {
3589 ethFrameExtPMData[k] = uint64(val.(uint32))
3590 receivedMask |= 0x1
3591 } else if !ok {
3592 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3593 }
3594 default:
3595 //do nothing
3596 }
3597 }
3598 }
3599 default:
3600 //do nothing
3601 }
3602 return receivedMask
3603}
3604
3605// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003606func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303607 receivedMask := uint16(0)
3608 switch requestedAttributesMask {
3609 case 0x3800:
3610 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3611 if _, ok := ethFrameExtPMData[k]; !ok {
3612 switch k {
3613 case "drop_events":
3614 if val, ok := meAttributes[dropEvents]; ok && val != nil {
3615 ethFrameExtPMData[k] = val.(uint64)
3616 receivedMask |= 0x2000
3617 } else if !ok {
3618 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3619 }
3620 case "octets":
3621 if val, ok := meAttributes[octets]; ok && val != nil {
3622 ethFrameExtPMData[k] = val.(uint64)
3623 receivedMask |= 0x1000
3624 } else if !ok {
3625 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3626 }
3627 case "frames":
3628 if val, ok := meAttributes[frames]; ok && val != nil {
3629 ethFrameExtPMData[k] = val.(uint64)
3630 receivedMask |= 0x800
3631 } else if !ok {
3632 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3633 }
3634 }
3635 }
3636 }
3637 case 0x0700:
3638 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3639 if _, ok := ethFrameExtPMData[k]; !ok {
3640 switch k {
3641 case "broadcast_frames":
3642 if val, ok := meAttributes[broadcastFrames]; ok && val != nil {
3643 ethFrameExtPMData[k] = val.(uint64)
3644 receivedMask |= 0x400
3645 } else if !ok {
3646 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3647 }
3648 case "multicast_frames":
3649 if val, ok := meAttributes[multicastFrames]; ok && val != nil {
3650 ethFrameExtPMData[k] = val.(uint64)
3651 receivedMask |= 0x200
3652 } else if !ok {
3653 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3654 }
3655 case "crc_errored_frames":
3656 if val, ok := meAttributes[crcErroredFrames]; ok && val != nil {
3657 ethFrameExtPMData[k] = val.(uint64)
3658 receivedMask |= 0x100
3659 } else if !ok {
3660 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3661 }
3662 }
3663 }
3664 }
3665 case 0x00E0:
3666 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3667 if _, ok := ethFrameExtPMData[k]; !ok {
3668 switch k {
3669 case "undersize_frames":
3670 if val, ok := meAttributes[undersizeFrames]; ok && val != nil {
3671 ethFrameExtPMData[k] = val.(uint64)
3672 receivedMask |= 0x80
3673 } else if !ok {
3674 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3675 }
3676 case "oversize_frames":
3677 if val, ok := meAttributes[oversizeFrames]; ok && val != nil {
3678 ethFrameExtPMData[k] = val.(uint64)
3679 receivedMask |= 0x40
3680 } else if !ok {
3681 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3682 }
3683 case "64_octets":
3684 if val, ok := meAttributes[frames64Octets]; ok && val != nil {
3685 ethFrameExtPMData[k] = val.(uint64)
3686 receivedMask |= 0x20
3687 } else if !ok {
3688 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3689 }
3690 }
3691 }
3692 }
3693 case 0x001C:
3694 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3695 if _, ok := ethFrameExtPMData[k]; !ok {
3696 switch k {
3697 case "65_to_127_octets":
3698 if val, ok := meAttributes[frames65To127Octets]; ok && val != nil {
3699 ethFrameExtPMData[k] = val.(uint64)
3700 receivedMask |= 0x10
3701 } else if !ok {
3702 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3703 }
3704 case "128_to_255_octets":
3705 if val, ok := meAttributes[frames128To255Octets]; ok && val != nil {
3706 ethFrameExtPMData[k] = val.(uint64)
3707 receivedMask |= 0x8
3708 } else if !ok {
3709 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3710 }
3711 case "256_to_511_octets":
3712 if val, ok := meAttributes[frames256To511Octets]; ok && val != nil {
3713 ethFrameExtPMData[k] = val.(uint64)
3714 receivedMask |= 0x4
3715 } else if !ok {
3716 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3717 }
3718 default:
3719 //do nothing
3720 }
3721 }
3722 }
3723 case 0x0003:
3724 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3725 if _, ok := ethFrameExtPMData[k]; !ok {
3726 switch k {
3727 case "512_to_1023_octets":
3728 if val, ok := meAttributes[frames512To1023Octets]; ok && val != nil {
3729 ethFrameExtPMData[k] = val.(uint64)
3730 receivedMask |= 0x2
3731 } else if !ok {
3732 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3733 }
3734 case "1024_to_1518_octets":
3735 if val, ok := meAttributes[frames1024To1518Octets]; ok && val != nil {
3736 ethFrameExtPMData[k] = val.(uint64)
3737 receivedMask |= 0x1
3738 } else if !ok {
3739 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3740 }
3741 default:
3742 //do nothing
3743 }
3744 }
3745 }
3746 }
3747 return receivedMask
3748}
3749
Himani Chawlaee10b542021-09-20 16:46:40 +05303750func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3751 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303752 errorCounterValue := UnsupportedCounterValue64bit
3753 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3754 errorCounterValue = UnsupportedCounterValue32bit
3755 }
3756 var pmDataOut extension.OmciEthernetFrameExtendedPm
3757 if aggregate {
3758 if pmData.DropEvents != errorCounterValue {
3759 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3760 } else {
3761 pmDataOut.DropEvents = pmData.DropEvents
3762 }
3763 if pmData.Octets != errorCounterValue {
3764 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3765 } else {
3766 pmDataOut.Octets = pmData.Octets
3767 }
3768 if pmData.Frames != errorCounterValue {
3769 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3770 } else {
3771 pmDataOut.Frames = pmData.Frames
3772 }
3773 if pmData.BroadcastFrames != errorCounterValue {
3774 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3775 } else {
3776 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3777 }
3778 if pmData.MulticastFrames != errorCounterValue {
3779 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3780 } else {
3781 pmDataOut.MulticastFrames = pmData.MulticastFrames
3782 }
3783 if pmData.CrcErroredFrames != errorCounterValue {
3784 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3785 } else {
3786 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3787 }
3788 if pmData.UndersizeFrames != errorCounterValue {
3789 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3790 } else {
3791 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3792 }
3793 if pmData.OversizeFrames != errorCounterValue {
3794 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3795 } else {
3796 pmDataOut.OversizeFrames = pmData.OversizeFrames
3797 }
3798 if pmData.Frames_64Octets != errorCounterValue {
3799 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3800 } else {
3801 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3802 }
3803 if pmData.Frames_65To_127Octets != errorCounterValue {
3804 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3805 } else {
3806 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3807 }
3808 if pmData.Frames_128To_255Octets != errorCounterValue {
3809 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3810 } else {
3811 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3812 }
3813 if pmData.Frames_256To_511Octets != errorCounterValue {
3814 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3815 } else {
3816 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3817 }
3818 if pmData.Frames_512To_1023Octets != errorCounterValue {
3819 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3820 } else {
3821 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3822 }
3823 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3824 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3825 } else {
3826 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3827 }
3828 } else {
3829 pmDataOut.DropEvents = pmDataIn["drop_events"]
3830 pmDataOut.Octets = pmDataIn["octets"]
3831 pmDataOut.Frames = pmDataIn["frames"]
3832 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3833 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3834 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3835 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3836 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3837 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3838 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3839 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3840 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3841 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3842 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3843 }
3844 return pmDataOut
3845}
3846
Himani Chawlaee10b542021-09-20 16:46:40 +05303847func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303848 controlBlock := make([]uint16, 8)
3849 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3850 controlBlock[0] = 0
3851 // Next two bytes are for the parent class ID
3852 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3853 // Next two bytes are for the parent me instance id
3854 controlBlock[2] = entityID
3855 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303856 if reset {
3857 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3858 } else {
3859 controlBlock[3] = 0
3860 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303861 // Next two bytes are for tca disable
3862 controlBlock[4] = 0x4000 //tca global disable
3863 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3864 if upstream {
3865 controlBlock[5] = 1 << 0
3866 } else {
3867 controlBlock[5] = (1 << 0) | (1 << 1)
3868 }
3869 // Next two bytes are for tci - does not matter here
3870 controlBlock[6] = 0
3871 // Next two bytes are for reserved bits - does not matter here
3872 controlBlock[7] = 0
3873 return controlBlock
3874}