blob: ce258de64b9f6d3ae1c863d505369e6aff48f8ed [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"
Girish Gowdrae09a6202021-01-12 18:10:59 -080029 "github.com/opencord/omci-lib-go"
30 me "github.com/opencord/omci-lib-go/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
Girish Gowdra0e533642021-03-02 22:02:51 -0800258// KV Store related constants
259const (
Himani Chawla43f95ff2021-06-03 00:24:12 +0530260 cPmKvStorePrefix = "%s/openonu/pm-data/%s" // <some-base-path>/openonu/pm-data/<onu-device-id>
261 cPmAdd = "add"
262 cPmAdded = "added"
263 cPmRemove = "remove"
264 cPmRemoved = "removed"
265 cExtPmKvStorePrefix = "%s/omci_me" //<some-base-path>/omci_me/<onu_vendor>/<onu_equipment_id>/<onu_sw_version>
Girish Gowdra0e533642021-03-02 22:02:51 -0800266)
267
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800268// Defines the type for generic metric population function
269type groupMetricPopulateFunc func(context.Context, me.ClassID, uint16, me.AttributeValueMap, me.AttributeValueMap, map[string]float32, *int) error
270
Girish Gowdrae0140f02021-02-02 16:55:09 -0800271// *** Classical L2 PM Counters end ***
272
Girish Gowdra0e533642021-03-02 22:02:51 -0800273type pmMEData struct {
274 InstancesActive []uint16 `json:"instances_active"` // list of active ME instance IDs for the group
275 InstancesToDelete []uint16 `json:"instances_to_delete"` // list of ME instance IDs marked for deletion for the group
276 InstancesToAdd []uint16 `json:"instances_to_add"` // list of ME instance IDs marked for addition for the group
277}
278
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800279type groupMetric struct {
280 groupName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000281 Enabled bool
282 Frequency uint32 // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800283 metricMap map[string]voltha.PmConfig_PmType
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000284 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
285 IsL2PMCounter bool // true for only L2 PM counters
Girish Gowdrae0140f02021-02-02 16:55:09 -0800286 collectAttempts uint32 // number of attempts to collect L2 PM data
Girish Gowdra0e533642021-03-02 22:02:51 -0800287 pmMEData *pmMEData
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800288}
289
290type standaloneMetric struct {
291 metricName string
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000292 Enabled bool
293 Frequency uint32 // valid only if FrequencyOverride is enabled.
294 NextCollectionInterval time.Time // valid only if FrequencyOverride is enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800295}
296
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000297// OnuMetricsManager - TODO: add comment
298type OnuMetricsManager struct {
299 deviceID string
300 pDeviceHandler cmn.IdeviceHandler
301 pOnuDeviceEntry cmn.IonuDeviceEntry
302 PAdaptFsm *cmn.AdapterFsm
Girish Gowdrae09a6202021-01-12 18:10:59 -0800303
Himani Chawlaee10b542021-09-20 16:46:40 +0530304 opticalMetricsChan chan me.AttributeValueMap
305 uniStatusMetricsChan chan me.AttributeValueMap
306 l2PmChan chan me.AttributeValueMap
307 extendedPmMeChan chan me.AttributeValueMap
308 syncTimeResponseChan chan bool // true is success, false is fail
309 l2PmCreateOrDeleteResponseChan chan bool // true is success, false is fail
310 extendedPMMeResponseChan chan me.Results // true is sucesss, false is fail
Girish Gowdrae0140f02021-02-02 16:55:09 -0800311
312 activeL2Pms []string // list of active l2 pm MEs created on the ONU.
313 l2PmToDelete []string // list of L2 PMs to delete
314 l2PmToAdd []string // list of L2 PM to add
Girish Gowdrae09a6202021-01-12 18:10:59 -0800315
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000316 GroupMetricMap map[string]*groupMetric
317 StandaloneMetricMap map[string]*standaloneMetric
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800318
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000319 StopProcessingOmciResponses chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700320 omciProcessingActive bool
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800321
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000322 StopTicks chan bool
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -0700323 tickGenerationActive bool
Girish Gowdrae0140f02021-02-02 16:55:09 -0800324
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000325 NextGlobalMetricCollectionTime time.Time // valid only if pmConfig.FreqOverride is set to false.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800326
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000327 OnuMetricsManagerLock sync.RWMutex
Girish Gowdra0e533642021-03-02 22:02:51 -0800328
329 pmKvStore *db.Backend
Himani Chawla43f95ff2021-06-03 00:24:12 +0530330
331 supportedEthernetFrameExtendedPMClass me.ClassID
Himani Chawlac77d5372021-07-12 15:42:26 +0530332 ethernetFrameExtendedPmUpStreamMEByEntityID map[uint16]*me.ManagedEntity
333 ethernetFrameExtendedPmDownStreamMEByEntityID map[uint16]*me.ManagedEntity
Himani Chawla43f95ff2021-06-03 00:24:12 +0530334 extPmKvStore *db.Backend
335 onuEthernetFrameExtendedPmLock sync.RWMutex
336 isDeviceReadyToCollectExtendedPmStats bool
Himani Chawlaee10b542021-09-20 16:46:40 +0530337 isEthernetFrameExtendedPmOperationOngoing bool
Girish Gowdrae09a6202021-01-12 18:10:59 -0800338}
339
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000340// NewOnuMetricsManager returns a new instance of the NewOnuMetricsManager
Girish Gowdra0e533642021-03-02 22:02:51 -0800341// The metrics manager module is responsible for configuration and management of individual and group metrics.
342// Currently all the metrics are managed as a group which fall into two categories - L2 PM and "all others"
343// The L2 PM counters have a fixed 15min interval for PM collection while all other group counters have
344// the collection interval configurable.
345// The global PM config is part of the voltha.Device struct and is backed up on KV store (by rw-core).
346// This module also implements resiliency for L2 PM ME instances that are active/pending-delete/pending-add.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000347func NewOnuMetricsManager(ctx context.Context, dh cmn.IdeviceHandler, onuDev cmn.IonuDeviceEntry) *OnuMetricsManager {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800348
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000349 var metricsManager OnuMetricsManager
350 metricsManager.deviceID = dh.GetDeviceID()
351 logger.Debugw(ctx, "init-OnuMetricsManager", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800352 metricsManager.pDeviceHandler = dh
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000353 metricsManager.pOnuDeviceEntry = onuDev
Girish Gowdrae09a6202021-01-12 18:10:59 -0800354
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000355 commMetricsChan := make(chan cmn.Message)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800356 metricsManager.opticalMetricsChan = make(chan me.AttributeValueMap)
357 metricsManager.uniStatusMetricsChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800358 metricsManager.l2PmChan = make(chan me.AttributeValueMap)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530359 metricsManager.extendedPmMeChan = make(chan me.AttributeValueMap)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800360
361 metricsManager.syncTimeResponseChan = make(chan bool)
362 metricsManager.l2PmCreateOrDeleteResponseChan = make(chan bool)
Himani Chawlaee10b542021-09-20 16:46:40 +0530363 metricsManager.extendedPMMeResponseChan = make(chan me.Results)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800364
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000365 metricsManager.StopProcessingOmciResponses = make(chan bool)
366 metricsManager.StopTicks = make(chan bool)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800367
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000368 metricsManager.GroupMetricMap = make(map[string]*groupMetric)
369 metricsManager.StandaloneMetricMap = make(map[string]*standaloneMetric)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800370
Himani Chawlac77d5372021-07-12 15:42:26 +0530371 metricsManager.ethernetFrameExtendedPmUpStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
372 metricsManager.ethernetFrameExtendedPmDownStreamMEByEntityID = make(map[uint16]*me.ManagedEntity)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530373
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000374 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 -0800375 metricsManager.initializeAllGroupMetrics()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800376 }
377
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800378 metricsManager.populateLocalGroupMetricData(ctx)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800379
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800380 if err := metricsManager.initializeL2PmFsm(ctx, commMetricsChan); err != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800381 return nil
382 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800383
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800384 // initialize the next metric collection intervals.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000385 metricsManager.InitializeMetricCollectionTime(ctx)
Girish Gowdra0e533642021-03-02 22:02:51 -0800386
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000387 baseKvStorePath := fmt.Sprintf(cPmKvStorePrefix, dh.GetBackendPathPrefix(), metricsManager.deviceID)
388 metricsManager.pmKvStore = dh.SetBackend(ctx, baseKvStorePath)
Girish Gowdra0e533642021-03-02 22:02:51 -0800389 if metricsManager.pmKvStore == nil {
390 logger.Errorw(ctx, "Can't initialize pmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000391 log.Fields{"device-id": metricsManager.deviceID, "service": baseKvStorePath})
Girish Gowdra0e533642021-03-02 22:02:51 -0800392 return nil
393 }
Girish Gowdra50e56422021-06-01 16:46:04 -0700394 // restore data from KV store
395 if err := metricsManager.restorePmData(ctx); err != nil {
396 logger.Errorw(ctx, "error restoring pm data", log.Fields{"err": err})
397 // we continue given that it does not effect the actual services for the ONU,
398 // but there may be some negative effect on PM collection (there may be some mismatch in
399 // the actual PM config and what is present on the device).
400 }
Girish Gowdra0e533642021-03-02 22:02:51 -0800401
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000402 baseExtPmKvStorePath := fmt.Sprintf(cExtPmKvStorePrefix, dh.GetBackendPathPrefix())
403 metricsManager.extPmKvStore = dh.SetBackend(ctx, baseExtPmKvStorePath)
Himani Chawla43f95ff2021-06-03 00:24:12 +0530404 if metricsManager.extPmKvStore == nil {
405 logger.Errorw(ctx, "Can't initialize extPmKvStore - no backend connection to PM module",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000406 log.Fields{"device-id": metricsManager.deviceID, "service": baseExtPmKvStorePath})
Himani Chawla43f95ff2021-06-03 00:24:12 +0530407 return nil
408 }
409
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000410 logger.Info(ctx, "init-OnuMetricsManager completed", log.Fields{"device-id": metricsManager.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800411 return &metricsManager
412}
413
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000414// InitializeMetricCollectionTime - TODO: add comment
415func (mm *OnuMetricsManager) InitializeMetricCollectionTime(ctx context.Context) {
416 if mm.pDeviceHandler.GetPmConfigs().FreqOverride {
417 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to true, then group/standalone metric specific interval applies
418 mm.OnuMetricsManagerLock.Lock()
419 defer mm.OnuMetricsManagerLock.Unlock()
420 for _, v := range mm.GroupMetricMap {
421 if v.Enabled && !v.IsL2PMCounter { // L2 PM counter collection is managed in a L2PmFsm
422 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800423 }
424 }
425
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000426 for _, v := range mm.StandaloneMetricMap {
427 if v.Enabled {
428 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800429 }
430 }
431 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000432 // If mm.pDeviceHandler.GetPmConfigs().FreqOverride is set to false, then overall metric specific interval applies
433 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800434 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000435 logger.Infow(ctx, "initialized standalone group/metric collection time", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800436}
437
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000438// UpdateDefaultFrequency - TODO: add comment
439func (mm *OnuMetricsManager) UpdateDefaultFrequency(ctx context.Context, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800440 // Verify that the configured DefaultFrequency is > 0 and is a multiple of FrequencyGranularity
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800441 if pmConfigs.DefaultFreq == 0 || (pmConfigs.DefaultFreq > 0 && pmConfigs.DefaultFreq%FrequencyGranularity != 0) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800442 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", pmConfigs.DefaultFreq, FrequencyGranularity)
443 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", pmConfigs.DefaultFreq, FrequencyGranularity)
444 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000445 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = pmConfigs.DefaultFreq
446 // re-set the NextGlobalMetricCollectionTime based on the new DefaultFreq
447 mm.NextGlobalMetricCollectionTime = time.Now().Add(time.Duration(mm.pDeviceHandler.GetPmConfigs().DefaultFreq) * time.Second)
448 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 -0800449 return nil
450}
451
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000452// UpdateGroupFreq - TODO: add comment
453func (mm *OnuMetricsManager) UpdateGroupFreq(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800454 var newGroupFreq uint32
455 found := false
456 groupSliceIdx := 0
457 var group *voltha.PmGroupConfig
458 for groupSliceIdx, group = range pmConfigs.Groups {
459 if group.GroupName == aGroupName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800460 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
461 if group.GroupFreq == 0 || (group.GroupFreq > 0 && group.GroupFreq%FrequencyGranularity != 0) {
462 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", group.GroupFreq, FrequencyGranularity)
463 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", group.GroupFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800464 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800465 newGroupFreq = group.GroupFreq
466 found = true
467 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800468 }
469 }
470 // if not found update group freq and next collection interval for the group
471 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000472 logger.Errorw(ctx, "group name not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800473 return fmt.Errorf("group-name-not-found-%v", aGroupName)
474 }
475
476 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000477 mm.OnuMetricsManagerLock.Lock()
478 defer mm.OnuMetricsManagerLock.Unlock()
479 for k, v := range mm.GroupMetricMap {
480 if k == aGroupName && !v.IsL2PMCounter { // We cannot allow the L2 PM counter frequency to be updated. It is 15min fixed by OMCI spec
481 v.Frequency = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800482 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000483 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].GroupFreq = newGroupFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800484 // Also updated the next group metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000485 v.NextCollectionInterval = time.Now().Add(time.Duration(newGroupFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800486 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000487 logger.Infow(ctx, "group frequency updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800488 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800489 }
490 }
491 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000492 logger.Errorw(ctx, "group frequency not updated", log.Fields{"device-id": mm.deviceID, "newGroupFreq": newGroupFreq, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800493 return fmt.Errorf("internal-error-during-group-freq-update--groupname-%s-freq-%d", aGroupName, newGroupFreq)
494 }
495 return nil
496}
497
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000498// UpdateMetricFreq - TODO: add comment
499func (mm *OnuMetricsManager) UpdateMetricFreq(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800500 var newMetricFreq uint32
501 found := false
502 metricSliceIdx := 0
503 var metric *voltha.PmConfig
504 for metricSliceIdx, metric = range pmConfigs.Metrics {
505 if metric.Name == aMetricName {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800506 // freq 0 is not allowed and it should be multiple of FrequencyGranularity
507 if metric.SampleFreq == 0 || (metric.SampleFreq > 0 && metric.SampleFreq%FrequencyGranularity != 0) {
508 logger.Errorf(ctx, "frequency-%u-should-be-a-multiple-of-%u", metric.SampleFreq, FrequencyGranularity)
509 return fmt.Errorf("frequency-%d-should-be-a-multiple-of-%d", metric.SampleFreq, FrequencyGranularity)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800510 }
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800511 newMetricFreq = metric.SampleFreq
512 found = true
513 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800514 }
515 }
516 if !found {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000517 logger.Errorw(ctx, "metric name not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800518 return fmt.Errorf("metric-name-not-found-%v", aMetricName)
519 }
520
521 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000522 mm.OnuMetricsManagerLock.Lock()
523 defer mm.OnuMetricsManagerLock.Unlock()
524 for k, v := range mm.GroupMetricMap {
Girish Gowdraaf0ad632021-01-27 13:00:01 -0800525 if k == aMetricName {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000526 v.Frequency = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800527 // update internal pm config
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000528 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].SampleFreq = newMetricFreq
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800529 // Also updated the next standalone metric collection time from now
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000530 v.NextCollectionInterval = time.Now().Add(time.Duration(newMetricFreq) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800531 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000532 logger.Infow(ctx, "metric frequency updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800533 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800534 }
535 }
536 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000537 logger.Errorw(ctx, "metric frequency not updated", log.Fields{"device-id": mm.deviceID, "newMetricFreq": newMetricFreq, "aMetricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800538 return fmt.Errorf("internal-error-during-standalone-metric-update--matricnane-%s-freq-%d", aMetricName, newMetricFreq)
539 }
540 return nil
541}
542
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000543// UpdateGroupSupport - TODO: add comment
544func (mm *OnuMetricsManager) UpdateGroupSupport(ctx context.Context, aGroupName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800545 groupSliceIdx := 0
546 var group *voltha.PmGroupConfig
547
548 for groupSliceIdx, group = range pmConfigs.Groups {
549 if group.GroupName == aGroupName {
550 break
551 }
552 }
553 if group == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000554 logger.Errorw(ctx, "group metric not found", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800555 return fmt.Errorf("group-not-found--groupName-%s", aGroupName)
556 }
557
558 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000559 mm.OnuMetricsManagerLock.Lock()
560 defer mm.OnuMetricsManagerLock.Unlock()
561 for k, v := range mm.GroupMetricMap {
562 if k == aGroupName && v.Enabled != group.Enabled {
563 mm.pDeviceHandler.GetPmConfigs().Groups[groupSliceIdx].Enabled = group.Enabled
564 v.Enabled = group.Enabled
Girish Gowdrae0140f02021-02-02 16:55:09 -0800565 if group.Enabled {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000566 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800567 // If it is a L2 PM counter we need to mark the PM to be added
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800568 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800569 // 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 -0800570 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, v.groupName)
571
572 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
573 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
574 // take further action
575 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800576 mm.updateGemPortNTPInstanceToAddForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800577 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000578 } else if mm.pDeviceHandler.GetPmConfigs().FreqOverride { // otherwise just update the next collection interval
579 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800580 }
581 } else { // group counter is disabled
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000582 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800583 // If it is a L2 PM counter we need to mark the PM to be deleted
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800584 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, v.groupName)
Girish Gowdrae0140f02021-02-02 16:55:09 -0800585 // 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 -0800586 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, v.groupName)
587
588 // The GemPortHistory group requires some special handling as the instance IDs are not pre-defined
589 // unlike other L2 PM counters. We need to fetch the active gemport instance IDs in the system to
590 // take further action
591 if v.groupName == GemPortHistoryName {
Girish Gowdra36ccf7d2021-02-25 20:42:51 -0800592 mm.updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -0800593 }
Girish Gowdrae0140f02021-02-02 16:55:09 -0800594 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800595 }
596 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000597 if v.IsL2PMCounter {
Girish Gowdrae0140f02021-02-02 16:55:09 -0800598 logger.Infow(ctx, "l2 pm group metric support updated",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000599 log.Fields{"device-id": mm.deviceID, "groupName": aGroupName, "enabled": group.Enabled, "l2PmToAdd": mm.l2PmToAdd, "l2PmToDelete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -0800600 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000601 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 -0800602 }
603 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800604 }
605 }
606
607 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000608 logger.Errorw(ctx, "group metric support not updated", log.Fields{"device-id": mm.deviceID, "groupName": aGroupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800609 return fmt.Errorf("internal-error-during-group-support-update--groupName-%s", aGroupName)
610 }
611 return nil
612}
613
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000614// UpdateMetricSupport - TODO: add comment
615func (mm *OnuMetricsManager) UpdateMetricSupport(ctx context.Context, aMetricName string, pmConfigs *voltha.PmConfigs) error {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800616 metricSliceIdx := 0
617 var metric *voltha.PmConfig
618
619 for metricSliceIdx, metric = range pmConfigs.Metrics {
620 if metric.Name == aMetricName {
621 break
622 }
623 }
624
625 if metric == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000626 logger.Errorw(ctx, "standalone metric not found", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800627 return fmt.Errorf("metric-not-found--metricname-%s", aMetricName)
628 }
629
630 updated := false
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000631 mm.OnuMetricsManagerLock.Lock()
632 defer mm.OnuMetricsManagerLock.Unlock()
633 for k, v := range mm.StandaloneMetricMap {
634 if k == aMetricName && v.Enabled != metric.Enabled {
635 mm.pDeviceHandler.GetPmConfigs().Metrics[metricSliceIdx].Enabled = metric.Enabled
636 v.Enabled = metric.Enabled
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800637 // 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 +0000638 if metric.Enabled && mm.pDeviceHandler.GetPmConfigs().FreqOverride {
639 v.NextCollectionInterval = time.Now().Add(time.Duration(v.Frequency) * time.Second)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800640 }
641 updated = true
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000642 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 -0800643 break
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800644 }
645 }
646 if !updated {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000647 logger.Errorw(ctx, "standalone metric support not updated", log.Fields{"device-id": mm.deviceID, "metricName": aMetricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800648 return fmt.Errorf("internal-error-during-standalone-support-update--metricname-%s", aMetricName)
649 }
650 return nil
651}
652
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000653// CollectAllGroupAndStandaloneMetrics - TODO: add comment
654func (mm *OnuMetricsManager) CollectAllGroupAndStandaloneMetrics(ctx context.Context) {
655 if mm.pDeviceHandler.GetPmConfigs().Grouped { // metrics are managed as a group.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800656 go mm.collectAllGroupMetrics(ctx)
657 } else {
658 go mm.collectAllStandaloneMetrics(ctx)
659 }
660}
661
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000662func (mm *OnuMetricsManager) collectAllGroupMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800663 go func() {
664 logger.Debug(ctx, "startCollector before collecting optical metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300665 metricInfo, err := mm.collectOpticalMetrics(ctx)
666 if err != nil {
667 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000668 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300669 return
670 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800671 if metricInfo != nil {
672 mm.publishMetrics(ctx, metricInfo)
673 }
674 }()
675
676 go func() {
677 logger.Debug(ctx, "startCollector before collecting uni metrics")
ozgecanetsiab36ed572021-04-01 10:38:48 +0300678 metricInfo, err := mm.collectUniStatusMetrics(ctx)
679 if err != nil {
680 logger.Errorw(ctx, "collectOpticalMetrics failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000681 log.Fields{"device-id": mm.deviceID, "Error": err})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300682 return
683 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800684 if metricInfo != nil {
685 mm.publishMetrics(ctx, metricInfo)
686 }
687 }()
688
689 // Add more here
690}
691
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000692func (mm *OnuMetricsManager) collectAllStandaloneMetrics(ctx context.Context) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800693 // None exists as of now, add when available here
694}
695
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000696// CollectGroupMetric - TODO: add comment
697func (mm *OnuMetricsManager) CollectGroupMetric(ctx context.Context, groupName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800698 switch groupName {
699 case OpticalPowerGroupMetricName:
700 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300701 if mi, _ := mm.collectOpticalMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800702 mm.publishMetrics(ctx, mi)
703 }
704 }()
705 case UniStatusGroupMetricName:
706 go func() {
ozgecanetsiab36ed572021-04-01 10:38:48 +0300707 if mi, _ := mm.collectUniStatusMetrics(ctx); mi != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800708 mm.publishMetrics(ctx, mi)
709 }
710 }()
711 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000712 logger.Errorw(ctx, "unhandled group metric name", log.Fields{"device-id": mm.deviceID, "groupName": groupName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800713 }
714}
715
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000716// CollectStandaloneMetric - TODO: add comment
717func (mm *OnuMetricsManager) CollectStandaloneMetric(ctx context.Context, metricName string) {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800718 switch metricName {
719 // None exist as of now, add when available
720 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000721 logger.Errorw(ctx, "unhandled standalone metric name", log.Fields{"device-id": mm.deviceID, "metricName": metricName})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800722 }
723}
724
725// collectOpticalMetrics collects groups metrics related to optical power from ani-g ME.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000726func (mm *OnuMetricsManager) collectOpticalMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
727 logger.Debugw(ctx, "collectOpticalMetrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800728
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000729 mm.OnuMetricsManagerLock.RLock()
730 if !mm.GroupMetricMap[OpticalPowerGroupMetricName].Enabled {
731 mm.OnuMetricsManagerLock.RUnlock()
732 logger.Debugw(ctx, "optical power group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300733 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800734 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000735 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800736
Girish Gowdrae09a6202021-01-12 18:10:59 -0800737 var metricInfoSlice []*voltha.MetricInformation
738 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000739 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().OnuId)
740 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetProxyAddress().ChannelId)
741 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800742
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800743 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800744 mmd := voltha.MetricMetaData{
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800745 Title: OpticalPowerGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800746 Ts: float64(raisedTs),
747 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000748 DeviceId: mm.deviceID,
749 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
750 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800751 }
752
Girish Gowdrae09a6202021-01-12 18:10:59 -0800753 // get the ANI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000754 anigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800755loop:
756 for _, anigInstID := range anigInstKeys {
757 var meAttributes me.AttributeValueMap
758 opticalMetrics := make(map[string]float32)
759 // Get the ANI-G instance optical power attributes
760 requestedAttributes := me.AttributeValueMap{"OpticalSignalLevel": 0, "TransmitOpticalLevel": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000761 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.AniGClassID, anigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300762 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000763 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
764 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300765 return nil, err
766 }
767
768 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800769 select {
770 case meAttributes = <-mm.opticalMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000771 logger.Debugw(ctx, "received optical metrics", log.Fields{"device-id": mm.deviceID})
772 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
773 logger.Errorw(ctx, "timeout waiting for omci-get response for optical metrics", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800774 // The metrics will be empty in this case
775 break loop
776 }
777 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800778 for k := range OpticalPowerGroupMetrics {
779 switch k {
780 case "ani_g_instance_id":
781 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
782 opticalMetrics[k] = float32(val.(uint16))
783 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800784 case "transmit_power_dBm":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800785 if val, ok := meAttributes["TransmitOpticalLevel"]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000786 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800787 }
Girish Gowdrae20a4f62021-03-09 16:06:23 -0800788 case "receive_power_dBm":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800789 if val, ok := meAttributes["OpticalSignalLevel"]; ok && val != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000790 opticalMetrics[k] = float32(math.Round((float64(cmn.TwosComplementToSignedInt16(val.(uint16)))/500.0)*10) / 10) // convert to dBm rounded of to single decimal place
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800791 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800792 default:
793 // do nothing
794 }
795 }
796 }
797 // create slice of metrics given that there could be more than one ANI-G instance and
798 // optical metrics are collected per ANI-G instance
799 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: opticalMetrics}
800 metricInfoSlice = append(metricInfoSlice, &metricInfo)
801 }
802
ozgecanetsiab36ed572021-04-01 10:38:48 +0300803 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -0800804}
805
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800806// collectUniStatusMetrics collects UNI status group metric from various MEs (uni-g, pptp and veip).
Girish Gowdrae09a6202021-01-12 18:10:59 -0800807// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000808func (mm *OnuMetricsManager) collectUniStatusMetrics(ctx context.Context) ([]*voltha.MetricInformation, error) {
809 logger.Debugw(ctx, "collectUniStatusMetrics", log.Fields{"device-id": mm.deviceID})
810 mm.OnuMetricsManagerLock.RLock()
811 if !mm.GroupMetricMap[UniStatusGroupMetricName].Enabled {
812 mm.OnuMetricsManagerLock.RUnlock()
813 logger.Debugw(ctx, "uni status group metric is not enabled", log.Fields{"device-id": mm.deviceID})
ozgecanetsiab36ed572021-04-01 10:38:48 +0300814 return nil, nil
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800815 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000816 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800817
Girish Gowdrae09a6202021-01-12 18:10:59 -0800818 var metricInfoSlice []*voltha.MetricInformation
819 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000820 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
821 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
822 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800823
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800824 raisedTs := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -0800825 mmd := voltha.MetricMetaData{
Girish Gowdra9b1577b2021-04-21 12:56:13 -0700826 Title: UniStatusGroupMetricName,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800827 Ts: float64(raisedTs),
828 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000829 DeviceId: mm.deviceID,
830 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
831 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdrae09a6202021-01-12 18:10:59 -0800832 }
833
Girish Gowdrae09a6202021-01-12 18:10:59 -0800834 // get the UNI-G instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000835 unigInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.UniGClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800836loop1:
837 for _, unigInstID := range unigInstKeys {
838 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
839 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
840 unigMetrics := make(map[string]float32)
841 var meAttributes me.AttributeValueMap
842 // Get the UNI-G instance optical power attributes
843 requestedAttributes := me.AttributeValueMap{"AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000844 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.UniGClassID, unigInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300845 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000846 logger.Errorw(ctx, "UNI-G failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
847 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300848 return nil, err
849 }
850 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800851 // Wait for metrics or timeout
852 select {
853 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000854 logger.Debugw(ctx, "received uni-g metrics", log.Fields{"device-id": mm.deviceID})
855 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
856 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 -0800857 // The metrics could be empty in this case
858 break loop1
859 }
860 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800861 for k := range UniStatusGroupMetrics {
862 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800863 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800864 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
865 unigMetrics[k] = float32(val.(byte))
866 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800867 default:
868 // do nothing
869 }
870 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800871 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800872 entityID := val.(uint16)
873 unigMetrics["entity_id"] = float32(entityID)
874 // 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 +0000875 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
876 if uni.EntityID == entityID {
877 unigMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700878 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800879 }
880 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800881 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700882 unigMetrics["me_class_id"] = float32(me.UniGClassID)
Girish Gowdra0e533642021-03-02 22:02:51 -0800883
Girish Gowdrae09a6202021-01-12 18:10:59 -0800884 // create slice of metrics given that there could be more than one UNI-G instance
885 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: unigMetrics}
886 metricInfoSlice = append(metricInfoSlice, &metricInfo)
887 }
888 }
889
890 // get the PPTP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000891 pptpInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800892loop2:
893 for _, pptpInstID := range pptpInstKeys {
894 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
895 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
896 var meAttributes me.AttributeValueMap
897 pptpMetrics := make(map[string]float32)
898
Girish Gowdrad3436802021-06-28 13:15:40 -0700899 requestedAttributes := me.AttributeValueMap{"ConfigurationInd": 0, "OperationalState": 0, "AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000900 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.PhysicalPathTerminationPointEthernetUniClassID, pptpInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300901 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000902 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
903 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300904 return nil, err
905 }
906 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800907 // Wait for metrics or timeout
908 select {
909 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000910 logger.Debugw(ctx, "received pptp metrics", log.Fields{"device-id": mm.deviceID})
911 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
912 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800913 // The metrics could be empty in this case
914 break loop2
915 }
916
917 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800918 for k := range UniStatusGroupMetrics {
919 switch k {
Girish Gowdrad3436802021-06-28 13:15:40 -0700920 case "configuration_ind":
921 if val, ok := meAttributes["ConfigurationInd"]; ok && val != nil {
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800922 pptpMetrics[k] = float32(val.(byte))
923 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800924 case "oper_status":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800925 if val, ok := meAttributes["OperationalState"]; ok && val != nil {
926 pptpMetrics[k] = float32(val.(byte))
927 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800928 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800929 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
930 pptpMetrics[k] = float32(val.(byte))
931 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800932 default:
933 // do nothing
934 }
935 }
936 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800937 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -0800938 entityID := val.(uint16)
939 pptpMetrics["entity_id"] = float32(entityID)
940 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000941 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
942 if uni.EntityID == entityID {
943 pptpMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700944 break
Girish Gowdra0e533642021-03-02 22:02:51 -0800945 }
946 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800947 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -0700948 pptpMetrics["me_class_id"] = float32(me.PhysicalPathTerminationPointEthernetUniClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800949
Girish Gowdrae09a6202021-01-12 18:10:59 -0800950 // create slice of metrics given that there could be more than one PPTP instance and
951 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: pptpMetrics}
952 metricInfoSlice = append(metricInfoSlice, &metricInfo)
953 }
954
955 // get the VEIP instance IDs
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000956 veipInstKeys := mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.VirtualEthernetInterfacePointClassID)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800957loop3:
958 for _, veipInstID := range veipInstKeys {
959 // TODO: Include additional information in the voltha.MetricMetaData - like portno, uni-id, instance-id
960 // to uniquely identify this ME instance and also to correlate the ME instance to physical instance
961 var meAttributes me.AttributeValueMap
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800962 veipMetrics := make(map[string]float32)
Girish Gowdrae09a6202021-01-12 18:10:59 -0800963
964 requestedAttributes := me.AttributeValueMap{"OperationalState": 0, "AdministrativeState": 0}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000965 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, me.VirtualEthernetInterfacePointClassID, veipInstID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300966 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000967 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
968 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +0300969 return nil, err
970 }
971 if meInstance != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800972 // Wait for metrics or timeout
973 select {
974 case meAttributes = <-mm.uniStatusMetricsChan:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +0000975 logger.Debugw(ctx, "received veip metrics", log.Fields{"device-id": mm.deviceID})
976 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
977 logger.Errorw(ctx, "timeout waiting for omci-get response for uni status", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -0800978 // The metrics could be empty in this case
979 break loop3
980 }
981
982 // Populate metric only if it was enabled.
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800983 for k := range UniStatusGroupMetrics {
984 switch k {
Girish Gowdrae09a6202021-01-12 18:10:59 -0800985 case "oper_status":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800986 if val, ok := meAttributes["OperationalState"]; ok && val != nil {
987 veipMetrics[k] = float32(val.(byte))
988 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800989 case "uni_admin_state":
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800990 if val, ok := meAttributes["AdministrativeState"]; ok && val != nil {
991 veipMetrics[k] = float32(val.(byte))
992 }
Girish Gowdrae09a6202021-01-12 18:10:59 -0800993 default:
994 // do nothing
995 }
996 }
997 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800998
Girish Gowdra5a7c4922021-01-22 18:33:41 -0800999 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
Girish Gowdra0e533642021-03-02 22:02:51 -08001000 entityID := val.(uint16)
1001 veipMetrics["entity_id"] = float32(entityID)
1002 // TODO: Rlock needed for reading uniEntityMap? May not be needed given uniEntityMap is populated setup at initial ONU bring up
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001003 for _, uni := range *mm.pDeviceHandler.GetUniEntityMap() {
1004 if uni.EntityID == entityID {
1005 veipMetrics["uni_port_no"] = float32(uni.PortNo)
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001006 break
Girish Gowdra0e533642021-03-02 22:02:51 -08001007 }
1008 }
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001009 }
Girish Gowdrada3a52f2021-03-17 11:24:11 -07001010 veipMetrics["me_class_id"] = float32(me.VirtualEthernetInterfacePointClassID)
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001011
Girish Gowdrae09a6202021-01-12 18:10:59 -08001012 // create slice of metrics given that there could be more than one VEIP instance
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001013 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: veipMetrics}
Girish Gowdrae09a6202021-01-12 18:10:59 -08001014 metricInfoSlice = append(metricInfoSlice, &metricInfo)
1015 }
1016
ozgecanetsiab36ed572021-04-01 10:38:48 +03001017 return metricInfoSlice, nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001018}
1019
1020// publishMetrics publishes the metrics on kafka
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001021func (mm *OnuMetricsManager) publishMetrics(ctx context.Context, metricInfo []*voltha.MetricInformation) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001022 var ke voltha.KpiEvent2
Girish Gowdra5a7c4922021-01-22 18:33:41 -08001023 ts := time.Now().Unix()
Girish Gowdrae09a6202021-01-12 18:10:59 -08001024 ke.SliceData = metricInfo
1025 ke.Type = voltha.KpiEventType_slice
1026 ke.Ts = float64(ts)
1027
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001028 if err := mm.pDeviceHandler.GetEventProxy().SendKpiEvent(ctx, "STATS_EVENT", &ke, voltha.EventCategory_EQUIPMENT, voltha.EventSubCategory_ONU, ts); err != nil {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001029 logger.Errorw(ctx, "failed-to-send-pon-stats", log.Fields{"err": err})
1030 }
1031}
1032
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001033// ProcessOmciMessages - TODO: add comment
1034func (mm *OnuMetricsManager) ProcessOmciMessages(ctx context.Context) {
1035 logger.Infow(ctx, "Start routine to process OMCI-GET messages for device-id", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001036 // Flush metric collection channels to be safe.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001037 // It is possible that there is stale data on this channel if the ProcessOmciMessages routine
Girish Gowdrae09a6202021-01-12 18:10:59 -08001038 // is stopped right after issuing a OMCI-GET request and started again.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001039 // The ProcessOmciMessages routine will get stopped if startCollector routine (in device_handler.go)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001040 // is stopped - as a result of ONU going down.
1041 mm.flushMetricCollectionChannels(ctx)
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07001042 mm.updateOmciProcessingStatus(true)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001043 for {
1044 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001045 case <-mm.StopProcessingOmciResponses: // stop this routine
1046 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 -07001047 mm.updateOmciProcessingStatus(false)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001048 return
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001049 case message, ok := <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001050 if !ok {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001051 logger.Errorw(ctx, "Message couldn't be read from channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001052 continue
1053 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001054 logger.Debugw(ctx, "Received message on ONU metrics channel", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001055
1056 switch message.Type {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001057 case cmn.OMCI:
1058 msg, _ := message.Data.(cmn.OmciMessage)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001059 mm.handleOmciMessage(ctx, msg)
1060 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001061 logger.Warn(ctx, "Unknown message type received", log.Fields{"device-id": mm.deviceID, "message.Type": message.Type})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001062 }
1063 }
1064 }
1065}
1066
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001067func (mm *OnuMetricsManager) handleOmciMessage(ctx context.Context, msg cmn.OmciMessage) {
1068 logger.Debugw(ctx, "omci Msg", log.Fields{"device-id": mm.deviceID,
Girish Gowdrae09a6202021-01-12 18:10:59 -08001069 "msgType": msg.OmciMsg.MessageType, "msg": msg})
1070 switch msg.OmciMsg.MessageType {
1071 case omci.GetResponseType:
1072 //TODO: error handling
1073 _ = mm.handleOmciGetResponseMessage(ctx, msg)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001074 case omci.SynchronizeTimeResponseType:
1075 _ = mm.handleOmciSynchronizeTimeResponseMessage(ctx, msg)
1076 case omci.CreateResponseType:
1077 _ = mm.handleOmciCreateResponseMessage(ctx, msg)
1078 case omci.DeleteResponseType:
1079 _ = mm.handleOmciDeleteResponseMessage(ctx, msg)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301080 case omci.GetCurrentDataResponseType:
1081 _ = mm.handleOmciGetCurrentDataResponseMessage(ctx, msg)
Himani Chawlaee10b542021-09-20 16:46:40 +05301082 case omci.SetResponseType:
1083 _ = mm.handleOmciSetResponseMessage(ctx, msg)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001084 default:
1085 logger.Warnw(ctx, "Unknown Message Type", log.Fields{"msgType": msg.OmciMsg.MessageType})
1086
1087 }
1088}
1089
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001090func (mm *OnuMetricsManager) handleOmciGetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001091 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetResponse)
1092 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001093 logger.Errorw(ctx, "omci Msg layer could not be detected for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1094 return fmt.Errorf("omci Msg layer could not be detected for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001095 }
1096 msgObj, msgOk := msgLayer.(*omci.GetResponse)
1097 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001098 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1099 return fmt.Errorf("omci Msg layer could not be assigned for GetResponse - handling stopped: %s", mm.deviceID)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001100 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001101 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 -08001102 if msgObj.Result == me.Success {
1103 meAttributes := msgObj.Attributes
1104 switch msgObj.EntityClass {
1105 case me.AniGClassID:
1106 mm.opticalMetricsChan <- meAttributes
1107 return nil
1108 case me.UniGClassID:
1109 mm.uniStatusMetricsChan <- meAttributes
1110 return nil
1111 case me.PhysicalPathTerminationPointEthernetUniClassID:
1112 mm.uniStatusMetricsChan <- meAttributes
1113 return nil
1114 case me.VirtualEthernetInterfacePointClassID:
1115 mm.uniStatusMetricsChan <- meAttributes
1116 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001117 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
1118 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001119 me.EthernetPerformanceMonitoringHistoryDataClassID,
1120 me.FecPerformanceMonitoringHistoryDataClassID,
1121 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001122 mm.l2PmChan <- meAttributes
Himani Chawla43f95ff2021-06-03 00:24:12 +05301123 return nil
1124 case me.EthernetFrameExtendedPmClassID,
1125 me.EthernetFrameExtendedPm64BitClassID:
1126 mm.extendedPmMeChan <- meAttributes
1127 return nil
1128 default:
1129 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001130 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301131 }
1132 } else {
1133 meAttributes := msgObj.Attributes
1134 switch msgObj.EntityClass {
1135 case me.EthernetFrameExtendedPmClassID,
1136 me.EthernetFrameExtendedPm64BitClassID:
1137 // not all counters may be supported in which case we have seen some ONUs throwing
1138 // AttributeFailure error code, while correctly populating other counters it supports
1139 mm.extendedPmMeChan <- meAttributes
1140 return nil
Girish Gowdrae09a6202021-01-12 18:10:59 -08001141 default:
1142 logger.Errorw(ctx, "unhandled omci get response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001143 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae09a6202021-01-12 18:10:59 -08001144 }
1145 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001146 return fmt.Errorf("unhandled-omci-get-response-message")
1147}
1148
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001149func (mm *OnuMetricsManager) handleOmciGetCurrentDataResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Himani Chawla43f95ff2021-06-03 00:24:12 +05301150 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeGetCurrentDataResponse)
1151 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001152 logger.Errorw(ctx, "omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1153 return fmt.Errorf("omci Msg layer could not be detected for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301154 }
1155 msgObj, msgOk := msgLayer.(*omci.GetCurrentDataResponse)
1156 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001157 logger.Errorw(ctx, "omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1158 return fmt.Errorf("omci Msg layer could not be assigned for GetCurrentDataResponse - handling stopped: %s", mm.deviceID)
Himani Chawla43f95ff2021-06-03 00:24:12 +05301159 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001160 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 +05301161 if msgObj.Result == me.Success {
1162 meAttributes := msgObj.Attributes
1163 switch msgObj.EntityClass {
1164 case me.EthernetFrameExtendedPmClassID,
1165 me.EthernetFrameExtendedPm64BitClassID:
1166 mm.extendedPmMeChan <- meAttributes
1167 return nil
1168 default:
1169 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001170 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301171 }
1172 } else {
1173 meAttributes := msgObj.Attributes
1174 switch msgObj.EntityClass {
1175 case me.EthernetFrameExtendedPmClassID,
1176 me.EthernetFrameExtendedPm64BitClassID:
1177 // not all counters may be supported in which case we have seen some ONUs throwing
1178 // AttributeFailure error code, while correctly populating other counters it supports
1179 mm.extendedPmMeChan <- meAttributes
1180 return nil
1181 default:
1182 logger.Errorw(ctx, "unhandled omci get current data response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001183 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Himani Chawla43f95ff2021-06-03 00:24:12 +05301184 }
1185 }
1186 return fmt.Errorf("unhandled-omci-get-current-data-response-message")
1187}
1188
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001189func (mm *OnuMetricsManager) handleOmciSynchronizeTimeResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001190 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSynchronizeTimeResponse)
1191 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001192 logger.Errorw(ctx, "omci Msg layer could not be detected for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1193 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 -08001194 }
1195 msgObj, msgOk := msgLayer.(*omci.SynchronizeTimeResponse)
1196 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001197 logger.Errorw(ctx, "omci Msg layer could not be assigned for synchronize time response - handling stopped", log.Fields{"device-id": mm.deviceID})
1198 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 -08001199 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001200 logger.Debugw(ctx, "OMCI synchronize time response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001201 if msgObj.Result == me.Success {
1202 switch msgObj.EntityClass {
1203 case me.OnuGClassID:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001204 logger.Infow(ctx, "omci synchronize time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001205 mm.syncTimeResponseChan <- true
1206 return nil
1207 default:
1208 logger.Errorw(ctx, "unhandled omci message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001209 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001210 }
1211 }
1212 mm.syncTimeResponseChan <- false
1213 logger.Errorf(ctx, "unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
1214 return fmt.Errorf("unhandled-omci-synchronize-time-response-message--error-code-%v", msgObj.Result)
Girish Gowdrae09a6202021-01-12 18:10:59 -08001215}
1216
Himani Chawlaee10b542021-09-20 16:46:40 +05301217func (mm *OnuMetricsManager) handleOmciSetResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
1218 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeSetResponse)
1219 if msgLayer == nil {
1220 logger.Errorw(ctx, "omci Msg layer could not be detected for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1221 return fmt.Errorf("omci Msg layer could not be detected for SetResponse - handling stopped: %s", mm.deviceID)
1222 }
1223 msgObj, msgOk := msgLayer.(*omci.SetResponse)
1224 if !msgOk {
1225 logger.Errorw(ctx, "omci Msg layer could not be assigned for SetResponse - handling stopped", log.Fields{"device-id": mm.deviceID})
1226 return fmt.Errorf("omci Msg layer could not be assigned for SetResponse - handling stopped: %s", mm.deviceID)
1227 }
1228 logger.Debugw(ctx, "OMCI SetResponse Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj, "result": msgObj.Result})
1229 switch msgObj.EntityClass {
1230 case me.EthernetFrameExtendedPmClassID,
1231 me.EthernetFrameExtendedPm64BitClassID:
1232 mm.extendedPMMeResponseChan <- msgObj.Result
1233 return nil
1234 default:
1235 logger.Errorw(ctx, "unhandled omci set response message",
1236 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
1237 }
1238 return fmt.Errorf("unhandled-omci-set-response-message-%v", mm.deviceID)
1239}
1240
Girish Gowdrae09a6202021-01-12 18:10:59 -08001241// flushMetricCollectionChannels flushes all metric collection channels for any stale OMCI responses
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001242func (mm *OnuMetricsManager) flushMetricCollectionChannels(ctx context.Context) {
Girish Gowdrae09a6202021-01-12 18:10:59 -08001243 // flush commMetricsChan
1244 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001245 case <-mm.PAdaptFsm.CommChan:
Girish Gowdrae09a6202021-01-12 18:10:59 -08001246 logger.Debug(ctx, "flushed common metrics channel")
1247 default:
1248 }
1249
1250 // flush opticalMetricsChan
1251 select {
1252 case <-mm.opticalMetricsChan:
1253 logger.Debug(ctx, "flushed optical metrics channel")
1254 default:
1255 }
1256
1257 // flush uniStatusMetricsChan
1258 select {
1259 case <-mm.uniStatusMetricsChan:
1260 logger.Debug(ctx, "flushed uni status metrics channel")
1261 default:
1262 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001263
1264 // flush syncTimeResponseChan
1265 select {
1266 case <-mm.syncTimeResponseChan:
1267 logger.Debug(ctx, "flushed sync time response channel")
1268 default:
1269 }
1270
1271 // flush l2PmChan
1272 select {
1273 case <-mm.l2PmChan:
1274 logger.Debug(ctx, "flushed L2 PM collection channel")
1275 default:
1276 }
1277
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001278 // flush StopTicks
Girish Gowdrae0140f02021-02-02 16:55:09 -08001279 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001280 case <-mm.StopTicks:
1281 logger.Debug(ctx, "flushed StopTicks channel")
Girish Gowdrae0140f02021-02-02 16:55:09 -08001282 default:
1283 }
1284
1285}
1286
1287// ** L2 PM FSM Handlers start **
1288
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001289func (mm *OnuMetricsManager) l2PMFsmStarting(ctx context.Context, e *fsm.Event) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001290
Girish Gowdrae0140f02021-02-02 16:55:09 -08001291 // Loop through all the group metrics
1292 // If it is a L2 PM Interval metric and it is enabled, then if it is not in the
1293 // list of active L2 PM list then mark it for creation
1294 // It it is a L2 PM Interval metric and it is disabled, then if it is in the
1295 // list of active L2 PM list then mark it for deletion
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001296 mm.OnuMetricsManagerLock.Lock()
1297 for n, g := range mm.GroupMetricMap {
1298 if g.IsL2PMCounter { // it is a l2 pm counter
1299 if g.Enabled { // metric enabled.
Girish Gowdrae0140f02021-02-02 16:55:09 -08001300 found := false
1301 inner1:
1302 for _, v := range mm.activeL2Pms {
1303 if v == n {
1304 found = true // metric already present in active l2 pm list
1305 break inner1
1306 }
1307 }
1308 if !found { // metric not in active l2 pm list. Mark this to be added later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001309 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001310 }
1311 } else { // metric not enabled.
1312 found := false
1313 inner2:
1314 for _, v := range mm.activeL2Pms {
1315 if v == n {
1316 found = true // metric is found in active l2 pm list
1317 break inner2
1318 }
1319 }
1320 if found { // metric is found in active l2 pm list. Mark this to be deleted later
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001321 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, n)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001322 }
1323 }
1324 }
1325 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001326 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001327 logger.Debugw(ctx, "pms to add and delete",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001328 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd, "pms-to-delete": mm.l2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001329 go func() {
1330 // push a tick event to move to next state
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001331 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
1332 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001333 }
1334 }()
1335}
1336
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001337func (mm *OnuMetricsManager) l2PMFsmSyncTime(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001338 // Sync time with the ONU to establish 15min boundary for PM collection.
1339 if err := mm.syncTime(ctx); err != nil {
1340 go func() {
1341 time.Sleep(SyncTimeRetryInterval * time.Second) // retry to sync time after this timeout
1342 // This will result in FSM attempting to sync time again
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001343 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventFailure); err != nil {
1344 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001345 }
1346 }()
1347 }
1348 // Initiate a tick generation routine every L2PmCollectionInterval
1349 go mm.generateTicks(ctx)
1350
1351 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001352 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1353 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001354 }
1355 }()
1356}
1357
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001358func (mm *OnuMetricsManager) l2PMFsmNull(ctx context.Context, e *fsm.Event) {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001359 // 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 +00001360 mm.OnuMetricsManagerLock.Lock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001361 mm.activeL2Pms = nil
1362 mm.l2PmToAdd = nil
1363 mm.l2PmToDelete = nil
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001364 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001365 // If the FSM was stopped, then clear PM data from KV store
1366 // The FSM is stopped when ONU goes down. It is time to clear its data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001367 if e.Event == L2PmEventStop {
Girish Gowdra0e533642021-03-02 22:02:51 -08001368 _ = mm.clearPmGroupData(ctx) // ignore error
1369 }
1370
Girish Gowdrae0140f02021-02-02 16:55:09 -08001371}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001372func (mm *OnuMetricsManager) l2PMFsmIdle(ctx context.Context, e *fsm.Event) {
1373 logger.Debugw(ctx, "Enter state idle", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001374
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001375 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001376 numOfPmToDelete := len(mm.l2PmToDelete)
1377 numOfPmToAdd := len(mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001378 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001379
1380 if numOfPmToDelete > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001381 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 -08001382 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001383 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
1384 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001385 }
1386 }()
1387 } else if numOfPmToAdd > 0 {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001388 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 -08001389 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001390 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
1391 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001392 }
1393 }()
1394 }
1395}
1396
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001397func (mm *OnuMetricsManager) l2PmFsmCollectData(ctx context.Context, e *fsm.Event) {
1398 logger.Debugw(ctx, "state collect data", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001399 // Copy the activeL2Pms for which we want to collect the metrics since activeL2Pms can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001400 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001401 copyOfActiveL2Pms := make([]string, len(mm.activeL2Pms))
1402 _ = copy(copyOfActiveL2Pms, mm.activeL2Pms)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001403 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001404
1405 for _, n := range copyOfActiveL2Pms {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001406 var metricInfoSlice []*voltha.MetricInformation
Girish Gowdra0e533642021-03-02 22:02:51 -08001407
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001408 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1409 mm.OnuMetricsManagerLock.RLock()
1410 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1411 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1412 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001413
Girish Gowdrae0140f02021-02-02 16:55:09 -08001414 switch n {
1415 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001416 logger.Debugw(ctx, "state collect data - collecting data for EthernetFramePerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001417 for _, entityID := range copyOfEntityIDs {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001418 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, true, entityID); metricInfo != nil { // upstream
1419 metricInfoSlice = append(metricInfoSlice, metricInfo)
1420 }
1421 if metricInfo := mm.collectEthernetFramePerformanceMonitoringHistoryData(ctx, false, entityID); metricInfo != nil { // downstream
1422 metricInfoSlice = append(metricInfoSlice, metricInfo)
1423 }
1424 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001425 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001426 logger.Debugw(ctx, "state collect data - collecting data for EthernetPerformanceMonitoringHistoryData ME", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08001427 for _, entityID := range copyOfEntityIDs {
1428 if metricInfo := mm.collectEthernetUniHistoryData(ctx, entityID); metricInfo != nil { // upstream
1429 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001430 }
1431 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001432
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001433 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001434 for _, entityID := range copyOfEntityIDs {
1435 if metricInfo := mm.collectFecHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001436 metricInfoSlice = append(metricInfoSlice, metricInfo)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001437 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001438 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001439 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001440 for _, entityID := range copyOfEntityIDs {
1441 if metricInfo := mm.collectGemHistoryData(ctx, entityID); metricInfo != nil { // upstream
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001442 metricInfoSlice = append(metricInfoSlice, metricInfo)
1443 }
1444 }
1445
Girish Gowdrae0140f02021-02-02 16:55:09 -08001446 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001447 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001448 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001449 mm.handleMetricsPublish(ctx, n, metricInfoSlice)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001450 }
1451 // Does not matter we send success or failure here.
1452 // Those PMs that we failed to collect data will be attempted to collect again in the next PM collection cycle (assuming
1453 // we have not exceed max attempts to collect the PM data)
1454 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001455 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1456 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001457 }
1458 }()
1459}
1460
Girish Gowdra0e533642021-03-02 22:02:51 -08001461// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001462func (mm *OnuMetricsManager) l2PmFsmCreatePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001463 // Copy the l2PmToAdd for which we want to collect the metrics since l2PmToAdd can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001464 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001465 copyOfL2PmToAdd := make([]string, len(mm.l2PmToAdd))
1466 _ = copy(copyOfL2PmToAdd, mm.l2PmToAdd)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001467 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001468
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001469 logger.Debugw(ctx, "state create pm - start", log.Fields{"device-id": mm.deviceID, "pms-to-add": copyOfL2PmToAdd})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001470 for _, n := range copyOfL2PmToAdd {
1471 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001472 atLeastOneSuccess := false // flag indicates if at least one ME instance of the PM was successfully created.
1473 cnt := 0
Girish Gowdrae0140f02021-02-02 16:55:09 -08001474 switch n {
1475 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001476 // 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 +05301477 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001478 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001479 // Attach the EthernetFramePerformanceMonitoringHistoryData ME to MacBridgePortConfigData on the UNI port
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001480 entityID := cmn.MacBridgePortAniBaseEID + uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001481 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1482 inner1:
1483 // retry L2PmCreateAttempts times to create the instance of PM
1484 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001485 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1486 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001487 if err != nil {
1488 logger.Errorw(ctx, "EthernetPerformanceMonitoringHistoryME create or delete failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001489 log.Fields{"device-id": mm.deviceID})
1490 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001491 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001492 go func(p_pmFsm *cmn.AdapterFsm) {
1493 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001494 }(pPMFsm)
1495 }
1496 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001497 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001498 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001499 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetFramePerformanceMonitoringHistoryData"); resp {
1500 atLeastOneSuccess = true
1501 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1502 break inner1
1503 }
1504 }
1505 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1506 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001507 }
1508 }
1509 }
1510 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001511 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
1512 if uniPort.PortType == cmn.UniPPTP { // This metric is only applicable for PPTP Uni Type
Girish Gowdra0e533642021-03-02 22:02:51 -08001513 // Attach the EthernetPerformanceMonitoringHistoryData ME to PPTP port instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001514 entityID := uniPort.EntityID
Girish Gowdra0e533642021-03-02 22:02:51 -08001515 _ = mm.updatePmData(ctx, n, entityID, cPmAdd) // TODO: ignore error for now
1516 inner2:
1517 // retry L2PmCreateAttempts times to create the instance of PM
1518 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001519 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1520 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001521 if err != nil {
1522 logger.Errorw(ctx, "CreateOrDeleteEthernetUNIHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001523 log.Fields{"device-id": mm.deviceID})
1524 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001525 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001526 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001527 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001528 if resp = mm.waitForResponseOrTimeout(ctx, true, entityID, "EthernetPerformanceMonitoringHistoryData"); resp {
1529 atLeastOneSuccess = true
1530 _ = mm.updatePmData(ctx, n, entityID, cPmAdded) // TODO: ignore error for now
1531 break inner2
1532 }
1533 }
1534 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1535 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001536 }
1537 }
1538 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001539 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001540 for _, anigInstID := range mm.pOnuDeviceEntry.GetOnuDB().GetSortedInstKeys(ctx, me.AniGClassID) {
Girish Gowdra0e533642021-03-02 22:02:51 -08001541 // Attach the FecPerformanceMonitoringHistoryData ME to the ANI-G ME instance
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001542 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1543 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, anigInstID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001544 if err != nil {
1545 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001546 log.Fields{"device-id": mm.deviceID})
1547 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001548 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001549 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001550 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001551 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdd) // TODO: ignore error for now
1552 inner3:
1553 // retry L2PmCreateAttempts times to create the instance of PM
1554 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1555 if resp = mm.waitForResponseOrTimeout(ctx, true, anigInstID, "FecPerformanceMonitoringHistoryData"); resp {
1556 atLeastOneSuccess = true
1557 _ = mm.updatePmData(ctx, n, anigInstID, cPmAdded) // TODO: ignore error for now
1558 break inner3
1559 }
1560 }
1561 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1562 _ = mm.updatePmData(ctx, n, anigInstID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001563 }
1564 }
1565 case GemPortHistoryName:
1566
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001567 mm.OnuMetricsManagerLock.RLock()
1568 copyOfGemPortInstIDsToAdd := make([]uint16, len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd))
1569 _ = copy(copyOfGemPortInstIDsToAdd, mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd)
1570 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001571
1572 if len(copyOfGemPortInstIDsToAdd) == 0 {
1573 // If there are no gemport history MEs to be created, just skip further processing
1574 // Otherwise down below (after 'switch' case handling) we assume the ME creation failed because resp and atLeastOneSuccess flag are false.
1575 // 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 +00001576 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001577 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001578 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001579 continue
1580 }
1581
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001582 for _, v := range copyOfGemPortInstIDsToAdd {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001583 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1584 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, true, mm.PAdaptFsm.CommChan, v)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001585 if err != nil {
1586 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001587 log.Fields{"device-id": mm.deviceID})
1588 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001589 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001590 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001591 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001592 _ = mm.updatePmData(ctx, n, v, cPmAdd) // TODO: ignore error for now
1593 inner4:
1594 // retry L2PmCreateAttempts times to create the instance of PM
1595 for cnt = 0; cnt < L2PmCreateAttempts; cnt++ {
1596 if resp = mm.waitForResponseOrTimeout(ctx, true, v, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); resp {
1597 atLeastOneSuccess = true
1598 _ = mm.updatePmData(ctx, n, v, cPmAdded) // TODO: ignore error for now
1599 break inner4
1600 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001601 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001602 if cnt == L2PmCreateAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1603 _ = mm.updatePmData(ctx, n, v, cPmRemoved) // TODO: ignore error for now
1604 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001605 }
1606
Girish Gowdrae0140f02021-02-02 16:55:09 -08001607 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001608 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001609 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001610 // 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
1611 if atLeastOneSuccess {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001612 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001613 mm.activeL2Pms = mm.appendIfMissingString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001614 // gem ports can be added dynamically for perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToAdd
1615 // only if no more new gem port instances created.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001616 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001617 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
1618 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001619 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 +00001620 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001621 } else {
Girish Gowdra0e533642021-03-02 22:02:51 -08001622 // 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 -08001623 // 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 +00001624 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001625 logger.Debugw(ctx, "exceeded-max-add-retry-attempts--disabling-group", log.Fields{"groupName": n})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001626 mm.GroupMetricMap[n].Enabled = false
Girish Gowdra0e533642021-03-02 22:02:51 -08001627 mm.l2PmToAdd = mm.removeIfFoundString(mm.l2PmToAdd, n)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001628
Girish Gowdrae0140f02021-02-02 16:55:09 -08001629 logger.Warnw(ctx, "state create pm - failed to create pm",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001630 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001631 "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001632 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001633 }
1634 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001635 mm.OnuMetricsManagerLock.RLock()
1636 logger.Debugw(ctx, "state create pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-add": mm.l2PmToAdd})
1637 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001638 // Does not matter we send success or failure here.
1639 // Those PMs that we failed to create will be attempted to create again in the next PM creation cycle (assuming
1640 // we have not exceed max attempts to create the PM ME)
1641 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001642 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1643 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001644 }
1645 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001646 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001647}
1648
Girish Gowdra0e533642021-03-02 22:02:51 -08001649// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001650func (mm *OnuMetricsManager) l2PmFsmDeletePM(ctx context.Context, e *fsm.Event) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001651 // Copy the l2PmToDelete for which we want to collect the metrics since l2PmToDelete can change dynamically
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001652 mm.OnuMetricsManagerLock.RLock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001653 copyOfL2PmToDelete := make([]string, len(mm.l2PmToDelete))
1654 _ = copy(copyOfL2PmToDelete, mm.l2PmToDelete)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001655 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001656
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001657 logger.Debugw(ctx, "state delete pm", log.Fields{"device-id": mm.deviceID, "pms-to-delete": copyOfL2PmToDelete})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001658 for _, n := range copyOfL2PmToDelete {
1659 resp := false
Girish Gowdra0e533642021-03-02 22:02:51 -08001660 cnt := 0
1661 atLeastOneDeleteFailure := false
1662
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001663 // mm.GroupMetricMap[n].pmMEData.InstancesActive could dynamically change, so make a copy
1664 mm.OnuMetricsManagerLock.RLock()
1665 copyOfEntityIDs := make([]uint16, len(mm.GroupMetricMap[n].pmMEData.InstancesActive))
1666 _ = copy(copyOfEntityIDs, mm.GroupMetricMap[n].pmMEData.InstancesActive)
1667 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001668
1669 if len(copyOfEntityIDs) == 0 {
1670 // 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 +00001671 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001672 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1673 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1674 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 +00001675 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001676 continue
1677 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001678 logger.Debugw(ctx, "entities to delete", log.Fields{"device-id": mm.deviceID, "metricName": n, "entityIDs": copyOfEntityIDs})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001679 switch n {
1680 case EthernetBridgeHistoryName:
Girish Gowdrae0140f02021-02-02 16:55:09 -08001681 // 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 +05301682 for _, direction := range []bool{true, false} {
Girish Gowdra0e533642021-03-02 22:02:51 -08001683 for _, entityID := range copyOfEntityIDs {
1684 inner1:
1685 // retry L2PmDeleteAttempts times to delete the instance of PM
1686 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001687 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetPerformanceMonitoringHistoryME(
1688 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001689 if err != nil {
1690 logger.Errorw(ctx, "CreateOrDeleteEthernetPerformanceMonitoringHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001691 log.Fields{"device-id": mm.deviceID})
1692 pPMFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001693 if pPMFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001694 go func(p_pmFsm *cmn.AdapterFsm) {
1695 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001696 }(pPMFsm)
1697 }
1698 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetPerformanceMonitoringHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001699 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001700 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001701 _ = mm.updatePmData(ctx, n, entityID, cPmRemove) // TODO: ignore error for now
1702 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetFramePerformanceMonitoringHistoryData"); !resp {
1703 atLeastOneDeleteFailure = true
1704 } else {
1705 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1706 break inner1
1707 }
1708 }
1709 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1710 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdrae0140f02021-02-02 16:55:09 -08001711 }
1712 }
1713 }
1714 case EthernetUniHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001715 for _, entityID := range copyOfEntityIDs {
1716 inner2:
1717 // retry L2PmDeleteAttempts times to delete the instance of PM
1718 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001719 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetUniHistoryME(
1720 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001721 if err != nil {
1722 logger.Errorw(ctx, "CreateOrDeleteEthernetUniHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001723 log.Fields{"device-id": mm.deviceID})
1724 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03001725 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001726 go func(p_pmFsm *cmn.AdapterFsm) {
1727 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001728 }(pmFsm)
1729 return err
1730 }
1731 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteEthernetUniHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001732 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001733 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001734 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "EthernetPerformanceMonitoringHistoryData"); !resp {
Girish Gowdra0e533642021-03-02 22:02:51 -08001735 atLeastOneDeleteFailure = true
1736 } else {
1737 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001738 break inner2
Girish Gowdrae0140f02021-02-02 16:55:09 -08001739 }
1740 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001741 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1742 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1743 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001744 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001745 case FecHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001746 for _, entityID := range copyOfEntityIDs {
1747 inner3:
1748 // retry L2PmDeleteAttempts times to delete the instance of PM
1749 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001750 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteFecHistoryME(
1751 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001752 if err != nil {
1753 logger.Errorw(ctx, "CreateOrDeleteFecHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001754 log.Fields{"device-id": mm.deviceID})
1755 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001756 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteFecHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001757 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001758 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001759 if resp := mm.waitForResponseOrTimeout(ctx, false, entityID, "FecPerformanceMonitoringHistoryData"); !resp {
1760 atLeastOneDeleteFailure = true
1761 } else {
1762 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1763 break inner3
1764 }
1765 }
1766 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1767 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001768 }
1769 }
1770 case GemPortHistoryName:
Girish Gowdra0e533642021-03-02 22:02:51 -08001771 for _, entityID := range copyOfEntityIDs {
1772 inner4:
1773 // retry L2PmDeleteAttempts times to delete the instance of PM
1774 for cnt = 0; cnt < L2PmDeleteAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001775 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteGemPortHistoryME(
1776 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, false, mm.PAdaptFsm.CommChan, entityID)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001777 if err != nil {
1778 logger.Errorw(ctx, "CreateOrDeleteGemPortHistoryME failed, failure PM FSM!",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001779 log.Fields{"device-id": mm.deviceID})
1780 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03001781 return fmt.Errorf(fmt.Sprintf("CreateOrDeleteGemPortHistoryMe-failed-%s-%s",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001782 mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03001783 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001784 if resp = mm.waitForResponseOrTimeout(ctx, false, entityID, "GemPortNetworkCtpPerformanceMonitoringHistoryData"); !resp {
1785 atLeastOneDeleteFailure = true
1786 } else {
1787 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1788 break inner4
1789 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001790 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001791 if cnt == L2PmDeleteAttempts { // if we reached max attempts just give up hope on this given instance of the PM ME
1792 _ = mm.updatePmData(ctx, n, entityID, cPmRemoved) // TODO: ignore error for now
1793 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001794 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08001795 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001796 logger.Errorw(ctx, "unsupported l2 pm", log.Fields{"device-id": mm.deviceID, "name": n})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001797 }
Girish Gowdra0e533642021-03-02 22:02:51 -08001798 // If we could not completely clean up the PM ME then just give up.
1799 if atLeastOneDeleteFailure {
1800 logger.Warnw(ctx, "state delete pm - failed to delete at least one instance of the PM ME",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001801 log.Fields{"device-id": mm.deviceID, "metricName": n,
Girish Gowdra0e533642021-03-02 22:02:51 -08001802 "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001803 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001804 logger.Debugw(ctx, "exceeded-max-delete-retry-attempts--disabling-group", log.Fields{"groupName": n})
1805 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
1806 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001807 mm.GroupMetricMap[n].Enabled = false
1808 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08001809 } else { // success case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001810 mm.OnuMetricsManagerLock.Lock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001811 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, n)
Girish Gowdra69570d92021-04-22 18:26:20 -07001812 // gem ports can be deleted dynamically from perf monitoring. We want to clear the GemPortHistoryName from mm.l2PmToDelete
1813 // only if no more new gem port instances removed.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001814 if n != GemPortHistoryName || (n == GemPortHistoryName && len(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete) == 0) {
Girish Gowdra69570d92021-04-22 18:26:20 -07001815 mm.l2PmToDelete = mm.removeIfFoundString(mm.l2PmToDelete, n)
1816 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001817 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 +00001818 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001819 }
1820 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001821 mm.OnuMetricsManagerLock.RLock()
1822 logger.Debugw(ctx, "state delete pm - done", log.Fields{"device-id": mm.deviceID, "active-l2-pms": mm.activeL2Pms, "pms-to-delete": mm.l2PmToDelete})
1823 mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdrae0140f02021-02-02 16:55:09 -08001824 // Does not matter we send success or failure here.
1825 // Those PMs that we failed to delete will be attempted to create again in the next PM collection cycle
1826 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001827 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventSuccess); err != nil {
1828 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001829 }
1830 }()
ozgecanetsiab36ed572021-04-01 10:38:48 +03001831 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001832}
1833
1834// ** L2 PM FSM Handlers end **
1835
1836// syncTime synchronizes time with the ONU to establish a 15 min boundary for PM collection and reporting.
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001837func (mm *OnuMetricsManager) syncTime(ctx context.Context) error {
1838 if err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSyncTime(ctx, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan); err != nil {
1839 logger.Errorw(ctx, "cannot send sync time request", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001840 return err
1841 }
1842
1843 select {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001844 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
1845 logger.Errorw(ctx, "timed out waiting for sync time response from onu", log.Fields{"device-id": mm.deviceID})
1846 return fmt.Errorf("timed-out-waiting-for-sync-time-response-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001847 case syncTimeRes := <-mm.syncTimeResponseChan:
1848 if !syncTimeRes {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001849 return fmt.Errorf("failed-to-sync-time-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001850 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001851 logger.Infow(ctx, "sync time success", log.Fields{"device-id": mm.deviceID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001852 return nil
1853 }
1854}
1855
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001856func (mm *OnuMetricsManager) collectEthernetFramePerformanceMonitoringHistoryData(ctx context.Context, upstream bool, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001857 var mEnt *me.ManagedEntity
1858 var omciErr me.OmciErrors
1859 var classID me.ClassID
1860 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001861 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001862 meParam := me.ParamData{EntityID: entityID}
1863 if upstream {
1864 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataUpstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001865 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001866 return nil
1867 }
1868 classID = me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID
1869 } else {
1870 if mEnt, omciErr = me.NewEthernetFramePerformanceMonitoringHistoryDataDownstream(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001871 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001872 return nil
1873 }
1874 classID = me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID
1875 }
1876
Girish Gowdrae0140f02021-02-02 16:55:09 -08001877 intervalEndTime := -1
1878 ethPMHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001879 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethPMHistData, &intervalEndTime); err != nil {
1880 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001881 }
1882
1883 // Populate some relevant context for the EthernetFramePerformanceMonitoringHistoryData PM
1884 ethPMHistData["class_id"] = float32(classID)
1885 ethPMHistData["interval_end_time"] = float32(intervalEndTime)
1886 ethPMHistData["parent_class_id"] = float32(me.MacBridgeConfigurationDataClassID) // EthernetFramePerformanceMonitoringHistoryData is attached to MBPCD ME
1887 ethPMHistData["parent_entity_id"] = float32(entityID)
1888 if upstream {
1889 ethPMHistData["upstream"] = float32(1)
1890 } else {
1891 ethPMHistData["upstream"] = float32(0)
1892 }
1893
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001894 metricInfo := mm.populateOnuMetricInfo(EthernetBridgeHistoryName, ethPMHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001895
Girish Gowdrae0140f02021-02-02 16:55:09 -08001896 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001897 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "upstream": upstream, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001898 return &metricInfo
1899}
1900
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001901func (mm *OnuMetricsManager) collectEthernetUniHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdrae0140f02021-02-02 16:55:09 -08001902 var mEnt *me.ManagedEntity
1903 var omciErr me.OmciErrors
1904 var classID me.ClassID
1905 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001906 logger.Debugw(ctx, "collecting data for EthernetFramePerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001907 meParam := me.ParamData{EntityID: entityID}
1908 if mEnt, omciErr = me.NewEthernetPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001909 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001910 return nil
1911 }
1912 classID = me.EthernetPerformanceMonitoringHistoryDataClassID
1913
Girish Gowdrae0140f02021-02-02 16:55:09 -08001914 intervalEndTime := -1
1915 ethUniHistData := make(map[string]float32)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001916 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, ethUniHistData, &intervalEndTime); err != nil {
1917 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08001918 }
1919
1920 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1921 ethUniHistData["class_id"] = float32(classID)
1922 ethUniHistData["interval_end_time"] = float32(intervalEndTime)
1923
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001924 metricInfo := mm.populateOnuMetricInfo(EthernetUniHistoryName, ethUniHistData)
Girish Gowdrae0140f02021-02-02 16:55:09 -08001925
Girish Gowdrae0140f02021-02-02 16:55:09 -08001926 logger.Debugw(ctx, "collecting data for EthernetPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001927 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdrae0140f02021-02-02 16:55:09 -08001928 return &metricInfo
1929}
1930
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001931func (mm *OnuMetricsManager) collectFecHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001932 var mEnt *me.ManagedEntity
1933 var omciErr me.OmciErrors
1934 var classID me.ClassID
1935 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001936 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001937 meParam := me.ParamData{EntityID: entityID}
1938 if mEnt, omciErr = me.NewFecPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001939 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001940 return nil
1941 }
1942 classID = me.FecPerformanceMonitoringHistoryDataClassID
1943
1944 intervalEndTime := -1
1945 fecHistData := make(map[string]float32)
1946 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, fecHistData, &intervalEndTime); err != nil {
1947 return nil
1948 }
1949
1950 // Populate some relevant context for the EthernetPerformanceMonitoringHistoryData PM
1951 fecHistData["class_id"] = float32(classID)
1952 fecHistData["interval_end_time"] = float32(intervalEndTime)
1953
1954 metricInfo := mm.populateOnuMetricInfo(FecHistoryName, fecHistData)
1955
1956 logger.Debugw(ctx, "collecting data for FecPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001957 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001958 return &metricInfo
1959}
1960
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001961func (mm *OnuMetricsManager) collectGemHistoryData(ctx context.Context, entityID uint16) *voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001962 var mEnt *me.ManagedEntity
1963 var omciErr me.OmciErrors
1964 var classID me.ClassID
1965 var meAttributes me.AttributeValueMap
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001966 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001967 meParam := me.ParamData{EntityID: entityID}
1968 if mEnt, omciErr = me.NewGemPortNetworkCtpPerformanceMonitoringHistoryData(meParam); omciErr == nil || mEnt == nil || omciErr.GetError() != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001969 logger.Errorw(ctx, "error creating me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001970 return nil
1971 }
1972 classID = me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID
1973
1974 intervalEndTime := -1
1975 gemHistData := make(map[string]float32)
1976 if err := mm.populateGroupSpecificMetrics(ctx, mEnt, classID, entityID, meAttributes, gemHistData, &intervalEndTime); err != nil {
1977 return nil
1978 }
1979
1980 // Populate some relevant context for the GemPortNetworkCtpPerformanceMonitoringHistoryData PM
1981 gemHistData["class_id"] = float32(classID)
1982 gemHistData["interval_end_time"] = float32(intervalEndTime)
1983
1984 metricInfo := mm.populateOnuMetricInfo(GemPortHistoryName, gemHistData)
1985
1986 logger.Debugw(ctx, "collecting data for GemPortNetworkCtpPerformanceMonitoringHistoryData successful",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001987 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "metricInfo": metricInfo})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001988 return &metricInfo
1989}
1990
Girish Gowdrae0140f02021-02-02 16:55:09 -08001991// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00001992func (mm *OnuMetricsManager) populateEthernetBridgeHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08001993 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08001994 upstream := false
1995 if classID == me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID {
1996 upstream = true
1997 }
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07001998 // Insert "IntervalEndTime" as part of the requested attributes as we need this to compare the get responses when get request is multipart
1999 requestedAttributes["IntervalEndTime"] = 0
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002000 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002001 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002002 logger.Errorw(ctx, "GetME failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2003 pmFsm := mm.PAdaptFsm
ozgecanetsiab36ed572021-04-01 10:38:48 +03002004 if pmFsm != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002005 go func(p_pmFsm *cmn.AdapterFsm) {
2006 _ = p_pmFsm.PFsm.Event(L2PmEventFailure)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002007 }(pmFsm)
2008 return err
2009 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002010 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002011 }
2012 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002013 select {
2014 case meAttributes = <-mm.l2PmChan:
2015 logger.Debugw(ctx, "received ethernet pm history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002016 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
2017 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002018 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002019 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002020 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002021 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002022 }
2023 // 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 -08002024 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002025 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-bridge-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002026 }
2027 }
2028 for k := range EthernetBridgeHistory {
2029 // populate ethPMHistData only if metric key not already present (or populated), since it is possible that we populate
2030 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2031 if _, ok := ethPMHistData[k]; !ok {
2032 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002033 case "entity_id":
2034 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2035 ethPMHistData[k] = float32(val.(uint16))
2036 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002037 case "drop_events":
2038 if val, ok := meAttributes["DropEvents"]; ok && val != nil {
2039 ethPMHistData[k] = float32(val.(uint32))
2040 }
2041 case "octets":
2042 if val, ok := meAttributes["Octets"]; ok && val != nil {
2043 ethPMHistData[k] = float32(val.(uint32))
2044 }
2045 case "packets":
2046 if val, ok := meAttributes["Packets"]; ok && val != nil {
2047 ethPMHistData[k] = float32(val.(uint32))
2048 }
2049 case "broadcast_packets":
2050 if val, ok := meAttributes["BroadcastPackets"]; ok && val != nil {
2051 ethPMHistData[k] = float32(val.(uint32))
2052 }
2053 case "multicast_packets":
2054 if val, ok := meAttributes["MulticastPackets"]; ok && val != nil {
2055 ethPMHistData[k] = float32(val.(uint32))
2056 }
2057 case "crc_errored_packets":
2058 if val, ok := meAttributes["CrcErroredPackets"]; ok && val != nil {
2059 ethPMHistData[k] = float32(val.(uint32))
2060 }
2061 case "undersize_packets":
2062 if val, ok := meAttributes["UndersizePackets"]; ok && val != nil {
2063 ethPMHistData[k] = float32(val.(uint32))
2064 }
2065 case "oversize_packets":
2066 if val, ok := meAttributes["OversizePackets"]; ok && val != nil {
2067 ethPMHistData[k] = float32(val.(uint32))
2068 }
2069 case "64_octets":
2070 if val, ok := meAttributes["Packets64Octets"]; ok && val != nil {
2071 ethPMHistData[k] = float32(val.(uint32))
2072 }
2073 case "65_to_127_octets":
2074 if val, ok := meAttributes["Packets65To127Octets"]; ok && val != nil {
2075 ethPMHistData[k] = float32(val.(uint32))
2076 }
2077 case "128_to_255_octets":
2078 if val, ok := meAttributes["Packets128To255Octets"]; ok && val != nil {
2079 ethPMHistData[k] = float32(val.(uint32))
2080 }
2081 case "256_to_511_octets":
2082 if val, ok := meAttributes["Packets256To511Octets"]; ok && val != nil {
2083 ethPMHistData[k] = float32(val.(uint32))
2084 }
2085 case "512_to_1023_octets":
2086 if val, ok := meAttributes["Packets512To1023Octets"]; ok && val != nil {
2087 ethPMHistData[k] = float32(val.(uint32))
2088 }
2089 case "1024_to_1518_octets":
2090 if val, ok := meAttributes["Packets1024To1518Octets"]; ok && val != nil {
2091 ethPMHistData[k] = float32(val.(uint32))
2092 }
2093 default:
2094 // do nothing
2095 }
2096 }
2097 }
2098 return nil
2099}
2100
2101// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002102func (mm *OnuMetricsManager) populateEthernetUniHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdrae0140f02021-02-02 16:55:09 -08002103 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, ethPMUniHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002104 // 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 +03002105 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2106 requestedAttributes["IntervalEndTime"] = 0
2107 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002108 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002109 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002110 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2111 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2112 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002113 }
2114 if meInstance != nil {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002115 select {
2116 case meAttributes = <-mm.l2PmChan:
2117 logger.Debugw(ctx, "received ethernet uni history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002118 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2119 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdrae0140f02021-02-02 16:55:09 -08002120 logger.Errorw(ctx, "timeout waiting for omci-get response for ethernet uni history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002121 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002122 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002123 return fmt.Errorf("timeout-during-l2-pm-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002124 }
2125 // 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 -08002126 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002127 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-ethernet-uni-history-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002128 }
2129 }
2130 for k := range EthernetUniHistory {
2131 // populate ethPMUniHistData only if metric key not already present (or populated), since it is possible that we populate
2132 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2133 if _, ok := ethPMUniHistData[k]; !ok {
2134 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002135 case "entity_id":
2136 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2137 ethPMUniHistData[k] = float32(val.(uint16))
2138 }
Girish Gowdrae0140f02021-02-02 16:55:09 -08002139 case "fcs_errors":
2140 if val, ok := meAttributes["FcsErrors"]; ok && val != nil {
2141 ethPMUniHistData[k] = float32(val.(uint32))
2142 }
2143 case "excessive_collision_counter":
2144 if val, ok := meAttributes["ExcessiveCollisionCounter"]; ok && val != nil {
2145 ethPMUniHistData[k] = float32(val.(uint32))
2146 }
2147 case "late_collision_counter":
2148 if val, ok := meAttributes["LateCollisionCounter"]; ok && val != nil {
2149 ethPMUniHistData[k] = float32(val.(uint32))
2150 }
2151 case "frames_too_long":
2152 if val, ok := meAttributes["FramesTooLong"]; ok && val != nil {
2153 ethPMUniHistData[k] = float32(val.(uint32))
2154 }
2155 case "buffer_overflows_on_rx":
2156 if val, ok := meAttributes["BufferOverflowsOnReceive"]; ok && val != nil {
2157 ethPMUniHistData[k] = float32(val.(uint32))
2158 }
2159 case "buffer_overflows_on_tx":
2160 if val, ok := meAttributes["BufferOverflowsOnTransmit"]; ok && val != nil {
2161 ethPMUniHistData[k] = float32(val.(uint32))
2162 }
2163 case "single_collision_frame_counter":
2164 if val, ok := meAttributes["SingleCollisionFrameCounter"]; ok && val != nil {
2165 ethPMUniHistData[k] = float32(val.(uint32))
2166 }
2167 case "multiple_collisions_frame_counter":
2168 if val, ok := meAttributes["MultipleCollisionsFrameCounter"]; ok && val != nil {
2169 ethPMUniHistData[k] = float32(val.(uint32))
2170 }
2171 case "sqe_counter":
2172 if val, ok := meAttributes["SqeCounter"]; ok && val != nil {
2173 ethPMUniHistData[k] = float32(val.(uint32))
2174 }
2175 case "deferred_tx_counter":
2176 if val, ok := meAttributes["DeferredTransmissionCounter"]; ok && val != nil {
2177 ethPMUniHistData[k] = float32(val.(uint32))
2178 }
2179 case "internal_mac_tx_error_counter":
2180 if val, ok := meAttributes["InternalMacTransmitErrorCounter"]; ok && val != nil {
2181 ethPMUniHistData[k] = float32(val.(uint32))
2182 }
2183 case "carrier_sense_error_counter":
2184 if val, ok := meAttributes["CarrierSenseErrorCounter"]; ok && val != nil {
2185 ethPMUniHistData[k] = float32(val.(uint32))
2186 }
2187 case "alignment_error_counter":
2188 if val, ok := meAttributes["AlignmentErrorCounter"]; ok && val != nil {
2189 ethPMUniHistData[k] = float32(val.(uint32))
2190 }
2191 case "internal_mac_rx_error_counter":
2192 if val, ok := meAttributes["InternalMacReceiveErrorCounter"]; ok && val != nil {
2193 ethPMUniHistData[k] = float32(val.(uint32))
2194 }
2195 default:
2196 // do nothing
2197 }
2198 }
2199 }
2200 return nil
2201}
2202
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002203// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002204func (mm *OnuMetricsManager) populateFecHistoryMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002205 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, fecHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002206 // 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 +03002207 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2208 requestedAttributes["IntervalEndTime"] = 0
2209 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002210 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002211 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002212 logger.Errorw(ctx, "GetMe failed, failure PM FSM!", log.Fields{"device-id": mm.deviceID})
2213 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2214 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002215 }
2216 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002217 select {
2218 case meAttributes = <-mm.l2PmChan:
2219 logger.Debugw(ctx, "received fec history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002220 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2221 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002222 logger.Errorw(ctx, "timeout waiting for omci-get response for fec history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002223 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002224 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002225 return fmt.Errorf("timeout-during-l2-pm-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002226 }
2227 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2228 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002229 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-fec-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002230 }
2231 }
2232 for k := range FecHistory {
2233 // populate fecHistData only if metric key not already present (or populated), since it is possible that we populate
2234 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2235 if _, ok := fecHistData[k]; !ok {
2236 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002237 case "entity_id":
2238 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2239 fecHistData[k] = float32(val.(uint16))
2240 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002241 case "corrected_bytes":
2242 if val, ok := meAttributes["CorrectedBytes"]; ok && val != nil {
2243 fecHistData[k] = float32(val.(uint32))
2244 }
2245 case "corrected_code_words":
2246 if val, ok := meAttributes["CorrectedCodeWords"]; ok && val != nil {
2247 fecHistData[k] = float32(val.(uint32))
2248 }
2249 case "uncorrectable_code_words":
2250 if val, ok := meAttributes["UncorrectableCodeWords"]; ok && val != nil {
2251 fecHistData[k] = float32(val.(uint32))
2252 }
2253 case "total_code_words":
2254 if val, ok := meAttributes["TotalCodeWords"]; ok && val != nil {
2255 fecHistData[k] = float32(val.(uint32))
2256 }
2257 case "fec_seconds":
2258 if val, ok := meAttributes["FecSeconds"]; ok && val != nil {
2259 fecHistData[k] = float32(val.(uint16))
2260 }
2261 default:
2262 // do nothing
2263 }
2264 }
2265 }
2266 return nil
2267}
2268
2269// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002270func (mm *OnuMetricsManager) populateGemPortMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002271 meAttributes me.AttributeValueMap, requestedAttributes me.AttributeValueMap, gemPortHistData map[string]float32, intervalEndTime *int) error {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002272 // 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 +03002273 if _, ok := requestedAttributes["IntervalEndTime"]; !ok {
2274 requestedAttributes["IntervalEndTime"] = 0
2275 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002276 meInstance, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMe(ctx, classID, entityID, requestedAttributes, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
ozgecanetsiab36ed572021-04-01 10:38:48 +03002277 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002278 logger.Errorw(ctx, "GetMe failed", log.Fields{"device-id": mm.deviceID})
2279 _ = mm.PAdaptFsm.PFsm.Event(L2PmEventFailure)
2280 return fmt.Errorf(fmt.Sprintf("GetME-failed-%s-%s", mm.deviceID, err))
ozgecanetsiab36ed572021-04-01 10:38:48 +03002281 }
2282 if meInstance != nil {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002283 select {
2284 case meAttributes = <-mm.l2PmChan:
2285 logger.Debugw(ctx, "received gem port history data metrics",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002286 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
2287 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002288 logger.Errorw(ctx, "timeout waiting for omci-get response for gem port history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002289 log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002290 // The metrics will be empty in this case
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002291 return fmt.Errorf("timeout-during-l2-pm-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002292 }
2293 // verify that interval end time has not changed during metric collection. If it changed, we abort the procedure
2294 if valid := mm.updateAndValidateIntervalEndTime(ctx, entityID, meAttributes, intervalEndTime); !valid {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002295 return fmt.Errorf("interval-end-time-changed-during-metric-collection-for-gemport-history-%v", mm.deviceID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002296 }
2297 }
2298 for k := range GemPortHistory {
2299 // populate gemPortHistData only if metric key not already present (or populated), since it is possible that we populate
2300 // the attributes in multiple iterations for a given L2 PM ME as there is a limit on the max OMCI GET payload size.
2301 if _, ok := gemPortHistData[k]; !ok {
2302 switch k {
Girish Gowdra0e533642021-03-02 22:02:51 -08002303 case "entity_id":
2304 if val, ok := meAttributes["ManagedEntityId"]; ok && val != nil {
2305 gemPortHistData[k] = float32(val.(uint16))
2306 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002307 case "transmitted_gem_frames":
2308 if val, ok := meAttributes["TransmittedGemFrames"]; ok && val != nil {
2309 gemPortHistData[k] = float32(val.(uint32))
2310 }
2311 case "received_gem_frames":
2312 if val, ok := meAttributes["ReceivedGemFrames"]; ok && val != nil {
2313 gemPortHistData[k] = float32(val.(uint32))
2314 }
2315 case "received_payload_bytes":
2316 if val, ok := meAttributes["ReceivedPayloadBytes"]; ok && val != nil {
2317 gemPortHistData[k] = float32(val.(uint64))
2318 }
2319 case "transmitted_payload_bytes":
2320 if val, ok := meAttributes["TransmittedPayloadBytes"]; ok && val != nil {
2321 gemPortHistData[k] = float32(val.(uint64))
2322 }
2323 case "encryption_key_errors":
2324 if val, ok := meAttributes["EncryptionKeyErrors"]; ok && val != nil {
2325 gemPortHistData[k] = float32(val.(uint32))
2326 }
2327 default:
2328 // do nothing
2329 }
2330 }
2331 }
2332 return nil
2333}
2334
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002335func (mm *OnuMetricsManager) handleOmciCreateResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002336 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeCreateResponse)
2337 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002338 logger.Errorw(ctx, "omci Msg layer could not be detected for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2339 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 -08002340 }
2341 msgObj, msgOk := msgLayer.(*omci.CreateResponse)
2342 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002343 logger.Errorw(ctx, "omci Msg layer could not be assigned for create response - handling stopped", log.Fields{"device-id": mm.deviceID})
2344 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 -08002345 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002346 logger.Debugw(ctx, "OMCI create response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002347 switch msgObj.EntityClass {
2348 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2349 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002350 me.EthernetPerformanceMonitoringHistoryDataClassID,
2351 me.FecPerformanceMonitoringHistoryDataClassID,
2352 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002353 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
2354 if msgObj.Result == me.Success || msgObj.Result == me.InstanceExists {
2355 mm.l2PmCreateOrDeleteResponseChan <- true
2356 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002357 logger.Warnw(ctx, "failed to create me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002358 mm.l2PmCreateOrDeleteResponseChan <- false
2359 }
2360 return nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05302361 case me.EthernetFrameExtendedPmClassID,
2362 me.EthernetFrameExtendedPm64BitClassID:
Himani Chawlaee10b542021-09-20 16:46:40 +05302363 mm.extendedPMMeResponseChan <- msgObj.Result
Himani Chawla43f95ff2021-06-03 00:24:12 +05302364 return nil
Girish Gowdrae0140f02021-02-02 16:55:09 -08002365 default:
2366 logger.Errorw(ctx, "unhandled omci create response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002367 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002368 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002369 return fmt.Errorf("unhandled-omci-create-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002370}
2371
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002372func (mm *OnuMetricsManager) handleOmciDeleteResponseMessage(ctx context.Context, msg cmn.OmciMessage) error {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002373 msgLayer := (*msg.OmciPacket).Layer(omci.LayerTypeDeleteResponse)
2374 if msgLayer == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002375 logger.Errorw(ctx, "omci Msg layer could not be detected for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2376 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 -08002377 }
2378 msgObj, msgOk := msgLayer.(*omci.DeleteResponse)
2379 if !msgOk {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002380 logger.Errorw(ctx, "omci Msg layer could not be assigned for delete response - handling stopped", log.Fields{"device-id": mm.deviceID})
2381 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 -08002382 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002383 logger.Debugw(ctx, "OMCI delete response Data", log.Fields{"device-id": mm.deviceID, "data-fields": msgObj})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002384 switch msgObj.EntityClass {
2385 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID,
2386 me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002387 me.EthernetPerformanceMonitoringHistoryDataClassID,
2388 me.FecPerformanceMonitoringHistoryDataClassID,
2389 me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
Girish Gowdrae0140f02021-02-02 16:55:09 -08002390 // If the result is me.UnknownInstance it means the entity was already deleted. It is ok handled that as success
2391 if msgObj.Result == me.Success || msgObj.Result == me.UnknownInstance {
2392 mm.l2PmCreateOrDeleteResponseChan <- true
2393 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002394 logger.Warnw(ctx, "failed to delete me", log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002395 mm.l2PmCreateOrDeleteResponseChan <- false
2396 }
2397 return nil
2398 default:
2399 logger.Errorw(ctx, "unhandled omci delete response message",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002400 log.Fields{"device-id": mm.deviceID, "class-id": msgObj.EntityClass})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002401 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002402 return fmt.Errorf("unhandled-omci-delete-response-message-%v", mm.deviceID)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002403}
2404
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002405func (mm *OnuMetricsManager) generateTicks(ctx context.Context) {
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002406 mm.updateTickGenerationStatus(true)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002407 for {
2408 select {
2409 case <-time.After(L2PmCollectionInterval * time.Second):
2410 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002411 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventTick); err != nil {
2412 logger.Errorw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdrae0140f02021-02-02 16:55:09 -08002413 }
2414 }()
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002415 case <-mm.StopTicks:
2416 logger.Infow(ctx, "stopping ticks", log.Fields{"device-id": mm.deviceID})
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002417 mm.updateTickGenerationStatus(false)
Girish Gowdrae0140f02021-02-02 16:55:09 -08002418 return
2419 }
2420 }
2421}
2422
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002423func (mm *OnuMetricsManager) handleMetricsPublish(ctx context.Context, metricName string, metricInfoSlice []*voltha.MetricInformation) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002424 // Publish metrics if it is valid
2425 if metricInfoSlice != nil {
2426 mm.publishMetrics(ctx, metricInfoSlice)
2427 } else {
2428 // If collectAttempts exceeds L2PmCollectAttempts then remove it from activeL2Pms
2429 // slice so that we do not collect data from that PM ME anymore
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002430 mm.OnuMetricsManagerLock.Lock()
2431 mm.GroupMetricMap[metricName].collectAttempts++
2432 if mm.GroupMetricMap[metricName].collectAttempts > L2PmCollectAttempts {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002433 mm.activeL2Pms = mm.removeIfFoundString(mm.activeL2Pms, metricName)
2434 }
2435 logger.Warnw(ctx, "state collect data - no metrics collected",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002436 log.Fields{"device-id": mm.deviceID, "metricName": metricName, "collectAttempts": mm.GroupMetricMap[metricName].collectAttempts})
2437 mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002438 }
2439}
2440
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002441func (mm *OnuMetricsManager) populateGroupSpecificMetrics(ctx context.Context, mEnt *me.ManagedEntity, classID me.ClassID, entityID uint16,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002442 meAttributes me.AttributeValueMap, data map[string]float32, intervalEndTime *int) error {
2443 var grpFunc groupMetricPopulateFunc
2444 switch classID {
2445 case me.EthernetFramePerformanceMonitoringHistoryDataUpstreamClassID, me.EthernetFramePerformanceMonitoringHistoryDataDownstreamClassID:
2446 grpFunc = mm.populateEthernetBridgeHistoryMetrics
2447 case me.EthernetPerformanceMonitoringHistoryDataClassID:
2448 grpFunc = mm.populateEthernetUniHistoryMetrics
2449 case me.FecPerformanceMonitoringHistoryDataClassID:
2450 grpFunc = mm.populateFecHistoryMetrics
2451 case me.GemPortNetworkCtpPerformanceMonitoringHistoryDataClassID:
2452 grpFunc = mm.populateGemPortMetrics
2453 default:
2454 return fmt.Errorf("unknown-classid-%v", classID)
2455 }
2456
2457 size := 0
2458 requestedAttributes := make(me.AttributeValueMap)
2459 for _, v := range mEnt.GetAttributeDefinitions() {
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002460 if v.Name == "ManagedEntityId" || v.Name == "IntervalEndTime" || v.Name == "ThresholdData12Id" {
2461 // Exclude the ManagedEntityId , it will be inserted by omci library based on 'entityID' information
2462 // Exclude IntervalEndTime. It will be inserted by the group PM populater function.
2463 // Exclude ThresholdData12Id as that is of no particular relevance for metrics collection.
2464 continue
2465 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002466 if (v.Size + size) <= MaxL2PMGetPayLoadSize {
2467 requestedAttributes[v.Name] = v.DefValue
2468 size = v.Size + size
2469 } else { // We exceeded the allow omci get size
2470 // Let's collect the attributes via get now and collect remaining in the next iteration
2471 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2472 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002473 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002474 return err
2475 }
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002476 requestedAttributes = make(me.AttributeValueMap) // reset map
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002477 requestedAttributes[v.Name] = v.DefValue // populate the metric that was missed in the current iteration
2478 size = v.Size // reset size
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002479 }
2480 }
2481 // Collect the omci get attributes for the last bunch of attributes.
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002482 if err := grpFunc(ctx, classID, entityID, meAttributes, requestedAttributes, data, intervalEndTime); err != nil {
2483 logger.Errorw(ctx, "error during metric collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002484 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Girish Gowdra6c04fbc2021-04-22 15:34:49 -07002485 return err
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002486 }
2487 return nil
2488}
2489
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002490func (mm *OnuMetricsManager) populateOnuMetricInfo(title string, data map[string]float32) voltha.MetricInformation {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002491 metricsContext := make(map[string]string)
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002492 metricsContext["onuID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.OnuId)
2493 metricsContext["intfID"] = fmt.Sprintf("%d", mm.pDeviceHandler.GetDevice().ProxyAddress.ChannelId)
2494 metricsContext["devicetype"] = mm.pDeviceHandler.GetDeviceType()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002495
2496 raisedTs := time.Now().Unix()
2497 mmd := voltha.MetricMetaData{
2498 Title: title,
2499 Ts: float64(raisedTs),
2500 Context: metricsContext,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002501 DeviceId: mm.deviceID,
2502 LogicalDeviceId: mm.pDeviceHandler.GetLogicalDeviceID(),
2503 SerialNo: mm.pDeviceHandler.GetDevice().SerialNumber,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002504 }
2505
2506 // create slice of metrics given that there could be more than one VEIP instance
2507 metricInfo := voltha.MetricInformation{Metadata: &mmd, Metrics: data}
2508 return metricInfo
2509}
2510
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002511func (mm *OnuMetricsManager) updateAndValidateIntervalEndTime(ctx context.Context, entityID uint16, meAttributes me.AttributeValueMap, intervalEndTime *int) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002512 valid := false
2513 if *intervalEndTime == -1 { // first time
2514 // Update the interval end time
2515 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2516 *intervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2517 valid = true
2518 }
2519 } else {
2520 var currIntervalEndTime int
2521 if val, ok := meAttributes["IntervalEndTime"]; ok && val != nil {
2522 currIntervalEndTime = int(meAttributes["IntervalEndTime"].(uint8))
2523 }
2524 if currIntervalEndTime != *intervalEndTime { // interval end time changed during metric collection
2525 logger.Errorw(ctx, "interval end time changed during metrics collection for ethernet pm history data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002526 log.Fields{"device-id": mm.deviceID, "entityID": entityID,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002527 "currIntervalEndTime": *intervalEndTime, "newIntervalEndTime": currIntervalEndTime})
2528 } else {
2529 valid = true
2530 }
2531 }
2532 return valid
2533}
2534
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002535func (mm *OnuMetricsManager) waitForResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassName string) bool {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002536 logger.Debugw(ctx, "waitForResponseOrTimeout", log.Fields{"create": create, "instID": instID, "meClassName": meClassName})
2537 select {
2538 case resp := <-mm.l2PmCreateOrDeleteResponseChan:
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002539 logger.Debugw(ctx, "received l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002540 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002541 return resp
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002542 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002543 logger.Errorw(ctx, "timeout waiting for l2 pm me response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002544 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassName": meClassName, "instID": instID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002545 }
2546 return false
2547}
2548
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002549func (mm *OnuMetricsManager) initializeGroupMetric(grpMtrcs map[string]voltha.PmConfig_PmType, grpName string, grpEnabled bool, grpFreq uint32) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002550 var pmConfigSlice []*voltha.PmConfig
2551 for k, v := range grpMtrcs {
Girish Gowdra0e533642021-03-02 22:02:51 -08002552 pmConfigSlice = append(pmConfigSlice,
2553 &voltha.PmConfig{
2554 Name: k,
2555 Type: v,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002556 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra0e533642021-03-02 22:02:51 -08002557 SampleFreq: grpFreq})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002558 }
2559 groupMetric := voltha.PmGroupConfig{
2560 GroupName: grpName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002561 Enabled: grpEnabled && mm.pDeviceHandler.GetMetricsEnabled(),
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002562 GroupFreq: grpFreq,
2563 Metrics: pmConfigSlice,
2564 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002565 mm.pDeviceHandler.GetPmConfigs().Groups = append(mm.pDeviceHandler.GetPmConfigs().Groups, &groupMetric)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002566
2567}
2568
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002569func (mm *OnuMetricsManager) initializeL2PmFsm(ctx context.Context, aCommChannel chan cmn.Message) error {
2570 mm.PAdaptFsm = cmn.NewAdapterFsm("L2PmFSM", mm.deviceID, aCommChannel)
2571 if mm.PAdaptFsm == nil {
2572 logger.Errorw(ctx, "L2PMFsm cmn.AdapterFsm could not be instantiated!!", log.Fields{
2573 "device-id": mm.deviceID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002574 return fmt.Errorf("nil-adapter-fsm")
2575 }
2576 // L2 PM FSM related state machine
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002577 mm.PAdaptFsm.PFsm = fsm.NewFSM(
2578 L2PmStNull,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002579 fsm.Events{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002580 {Name: L2PmEventInit, Src: []string{L2PmStNull}, Dst: L2PmStStarting},
2581 {Name: L2PmEventTick, Src: []string{L2PmStStarting}, Dst: L2PmStSyncTime},
2582 {Name: L2PmEventTick, Src: []string{L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe}, Dst: L2PmStCollectData},
2583 {Name: L2PmEventSuccess, Src: []string{L2PmStSyncTime, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2584 {Name: L2PmEventFailure, Src: []string{L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStIdle},
2585 {Name: L2PmEventFailure, Src: []string{L2PmStSyncTime}, Dst: L2PmStSyncTime},
2586 {Name: L2PmEventAddMe, Src: []string{L2PmStIdle}, Dst: L2PmStCreatePmMe},
2587 {Name: L2PmEventDeleteMe, Src: []string{L2PmStIdle}, Dst: L2PmStDeletePmMe},
2588 {Name: L2PmEventStop, Src: []string{L2PmStNull, L2PmStStarting, L2PmStSyncTime, L2PmStIdle, L2PmStCreatePmMe, L2PmStDeletePmMe, L2PmStCollectData}, Dst: L2PmStNull},
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002589 },
2590 fsm.Callbacks{
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002591 "enter_state": func(e *fsm.Event) { mm.PAdaptFsm.LogFsmStateChange(ctx, e) },
2592 "enter_" + L2PmStNull: func(e *fsm.Event) { mm.l2PMFsmNull(ctx, e) },
2593 "enter_" + L2PmStIdle: func(e *fsm.Event) { mm.l2PMFsmIdle(ctx, e) },
2594 "enter_" + L2PmStStarting: func(e *fsm.Event) { mm.l2PMFsmStarting(ctx, e) },
2595 "enter_" + L2PmStSyncTime: func(e *fsm.Event) { mm.l2PMFsmSyncTime(ctx, e) },
2596 "enter_" + L2PmStCollectData: func(e *fsm.Event) { mm.l2PmFsmCollectData(ctx, e) },
2597 "enter_" + L2PmStCreatePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmCreatePM(ctx, e) },
2598 "enter_" + L2PmStDeletePmMe: func(e *fsm.Event) { _ = mm.l2PmFsmDeletePM(ctx, e) },
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002599 },
2600 )
2601 return nil
2602}
2603
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002604func (mm *OnuMetricsManager) initializeAllGroupMetrics() {
2605 mm.pDeviceHandler.InitPmConfigs()
2606 mm.pDeviceHandler.GetPmConfigs().Id = mm.deviceID
2607 mm.pDeviceHandler.GetPmConfigs().DefaultFreq = DefaultMetricCollectionFrequency
2608 mm.pDeviceHandler.GetPmConfigs().Grouped = GroupMetricEnabled
2609 mm.pDeviceHandler.GetPmConfigs().FreqOverride = DefaultFrequencyOverrideEnabled
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002610
2611 // Populate group metrics.
2612 // Lets populate irrespective of GroupMetricEnabled is true or not.
2613 // The group metrics collection will decided on this flag later
2614
2615 mm.initializeGroupMetric(OpticalPowerGroupMetrics, OpticalPowerGroupMetricName,
2616 OpticalPowerGroupMetricEnabled, OpticalPowerMetricGroupCollectionFrequency)
2617
2618 mm.initializeGroupMetric(UniStatusGroupMetrics, UniStatusGroupMetricName,
2619 UniStatusGroupMetricEnabled, UniStatusMetricGroupCollectionFrequency)
2620
2621 // classical l2 pm counter start
2622
2623 mm.initializeGroupMetric(EthernetBridgeHistory, EthernetBridgeHistoryName,
2624 EthernetBridgeHistoryEnabled, EthernetBridgeHistoryFrequency)
2625
2626 mm.initializeGroupMetric(EthernetUniHistory, EthernetUniHistoryName,
2627 EthernetUniHistoryEnabled, EthernetUniHistoryFrequency)
2628
2629 mm.initializeGroupMetric(FecHistory, FecHistoryName,
2630 FecHistoryEnabled, FecHistoryFrequency)
2631
2632 mm.initializeGroupMetric(GemPortHistory, GemPortHistoryName,
2633 GemPortHistoryEnabled, GemPortHistoryFrequency)
2634
2635 // classical l2 pm counter end
2636
2637 // Add standalone metric (if present) after this (will be added to dh.pmConfigs.Metrics)
2638}
2639
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002640func (mm *OnuMetricsManager) populateLocalGroupMetricData(ctx context.Context) {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002641 // Populate local group metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002642 for _, g := range mm.pDeviceHandler.GetPmConfigs().Groups {
2643 mm.GroupMetricMap[g.GroupName] = &groupMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002644 groupName: g.GroupName,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002645 Enabled: g.Enabled,
2646 Frequency: g.GroupFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002647 }
2648 switch g.GroupName {
2649 case OpticalPowerGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002650 mm.GroupMetricMap[g.GroupName].metricMap = OpticalPowerGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002651 case UniStatusGroupMetricName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002652 mm.GroupMetricMap[g.GroupName].metricMap = UniStatusGroupMetrics
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002653 case EthernetBridgeHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002654 mm.GroupMetricMap[g.GroupName].metricMap = EthernetBridgeHistory
2655 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002656 case EthernetUniHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002657 mm.GroupMetricMap[g.GroupName].metricMap = EthernetUniHistory
2658 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002659 case FecHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002660 mm.GroupMetricMap[g.GroupName].metricMap = FecHistory
2661 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002662 case GemPortHistoryName:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002663 mm.GroupMetricMap[g.GroupName].metricMap = GemPortHistory
2664 mm.GroupMetricMap[g.GroupName].IsL2PMCounter = true
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002665 default:
2666 logger.Errorw(ctx, "unhandled-group-name", log.Fields{"groupName": g.GroupName})
2667 }
2668 }
2669
2670 // Populate local standalone metric structures
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002671 for _, m := range mm.pDeviceHandler.GetPmConfigs().Metrics {
2672 mm.StandaloneMetricMap[m.Name] = &standaloneMetric{
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002673 metricName: m.Name,
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002674 Enabled: m.Enabled,
2675 Frequency: m.SampleFreq,
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002676 }
2677 switch m.Name {
2678 // None exist as of now. Add when available.
2679 default:
2680 logger.Errorw(ctx, "unhandled-metric-name", log.Fields{"metricName": m.Name})
2681 }
2682 }
2683}
2684
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002685// AddGemPortForPerfMonitoring - TODO: add comment
2686func (mm *OnuMetricsManager) AddGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2687 mm.OnuMetricsManagerLock.Lock()
2688 defer mm.OnuMetricsManagerLock.Unlock()
2689 logger.Debugw(ctx, "add gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002690 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002691 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002692 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002693 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002694
2695 mm.l2PmToAdd = mm.appendIfMissingString(mm.l2PmToAdd, GemPortHistoryName)
2696 // We do not need to remove from l2PmToDelete slice as we could have Add and Delete of
2697 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2698 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2699 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002700
2701 logger.Debugw(ctx, "add gemport for perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002702 log.Fields{"device-id": mm.deviceID, "pms-to-add": mm.l2PmToAdd,
2703 "instances-to-add": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd})
Girish Gowdra69570d92021-04-22 18:26:20 -07002704 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002705 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventAddMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002706 // log at warn level as the gem port for monitoring is going to be added eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002707 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002708 }
2709 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002710}
2711
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002712// RemoveGemPortForPerfMonitoring - TODO: add comment
2713func (mm *OnuMetricsManager) RemoveGemPortForPerfMonitoring(ctx context.Context, gemPortNTPInstID uint16) {
2714 mm.OnuMetricsManagerLock.Lock()
2715 defer mm.OnuMetricsManagerLock.Unlock()
2716 logger.Debugw(ctx, "remove gemport for perf monitoring - start", log.Fields{"device-id": mm.deviceID, "gemPortID": gemPortNTPInstID})
2717 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002718 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002719 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, gemPortNTPInstID)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002720
2721 mm.l2PmToDelete = mm.appendIfMissingString(mm.l2PmToDelete, GemPortHistoryName)
2722 // We do not need to remove from l2PmToAdd slice as we could have Add and Delete of
2723 // GemPortPerfHistory ME simultaneously for different instances of the ME.
2724 // The creation or deletion of an instance is decided based on its presence in gemPortNCTPPerfHistInstToDelete or
2725 // gemPortNCTPPerfHistInstToAdd slice
Girish Gowdra69570d92021-04-22 18:26:20 -07002726
2727 logger.Debugw(ctx, "remove gemport from perf monitoring - end",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002728 log.Fields{"device-id": mm.deviceID, "pms-to-delete": mm.l2PmToDelete,
2729 "instances-to-delete": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra69570d92021-04-22 18:26:20 -07002730 go func() {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002731 if err := mm.PAdaptFsm.PFsm.Event(L2PmEventDeleteMe); err != nil {
Girish Gowdra69570d92021-04-22 18:26:20 -07002732 // log at warn level as the gem port for monitoring is going to be removed eventually
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002733 logger.Warnw(ctx, "error calling event", log.Fields{"device-id": mm.deviceID, "err": err})
Girish Gowdra69570d92021-04-22 18:26:20 -07002734 }
2735 }()
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002736}
2737
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002738func (mm *OnuMetricsManager) updateGemPortNTPInstanceToAddForPerfMonitoring(ctx context.Context) {
2739 if mm.pDeviceHandler.GetOnuTP() != nil {
2740 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002741 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002742 for _, v := range gemPortInstIDs {
2743 // mark the instance for addition
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002744 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002745 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToDelete slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002746 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002747 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002748 logger.Debugw(ctx, "updateGemPortNTPInstanceToAddForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002749 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002750 }
2751}
2752
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002753func (mm *OnuMetricsManager) updateGemPortNTPInstanceToDeleteForPerfMonitoring(ctx context.Context) {
2754 if mm.pDeviceHandler.GetOnuTP() != nil {
2755 gemPortInstIDs := mm.pDeviceHandler.GetOnuTP().GetAllBidirectionalGemPortIDsForOnu()
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002756 // NOTE: It is expected that caller of this function has acquired the required mutex for synchronization purposes
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002757 for _, v := range gemPortInstIDs {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002758 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002759 // If the instance presence toggles too soon, we need to remove it from gemPortNCTPPerfHistInstToAdd slice
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002760 mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd = mm.removeIfFoundUint16(mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, v)
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002761 }
2762 }
Girish Gowdra36ccf7d2021-02-25 20:42:51 -08002763 logger.Debugw(ctx, "updateGemPortNTPInstanceToDeleteForPerfMonitoring",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002764 log.Fields{"deviceID": mm.deviceID, "gemToAdd": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToAdd, "gemToDel": mm.GroupMetricMap[GemPortHistoryName].pmMEData.InstancesToDelete})
Girish Gowdra0e533642021-03-02 22:02:51 -08002765}
2766
2767// restorePmData restores any PM data available on the KV store to local cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002768func (mm *OnuMetricsManager) restorePmData(ctx context.Context) error {
2769 logger.Debugw(ctx, "restorePmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002770 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002771 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2772 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002773 }
2774 var errorsList []error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002775 for groupName, group := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002776 group.pmMEData = &pmMEData{}
2777 Value, err := mm.pmKvStore.Get(ctx, groupName)
2778 if err == nil {
2779 if Value != nil {
2780 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002781 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002782 tmpBytes, _ := kvstore.ToByte(Value.Value)
2783
2784 if err = json.Unmarshal(tmpBytes, &group.pmMEData); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002785 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
2786 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 -08002787 continue
2788 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002789 logger.Debugw(ctx, "restorePmData - success", log.Fields{"pmData": group.pmMEData, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002790 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002791 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002792 continue
2793 }
2794 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002795 logger.Errorw(ctx, "restorePmData - fail", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "err": err})
2796 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 -08002797 continue
2798 }
2799 }
2800 if len(errorsList) > 0 {
2801 return fmt.Errorf("errors-restoring-pm-data-for-one-or-more-groups--errors:%v", errorsList)
2802 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002803 logger.Debugw(ctx, "restorePmData - complete success", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002804 return nil
2805}
2806
2807// getPmData gets pmMEData from cache. Since we have write through cache implementation for pmMEData,
2808// the data must be available in cache.
2809// Note, it is expected that caller of this function manages the required synchronization (like using locks etc.).
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002810func (mm *OnuMetricsManager) getPmData(ctx context.Context, groupName string) (*pmMEData, error) {
2811 if grp, ok := mm.GroupMetricMap[groupName]; ok {
Girish Gowdra0e533642021-03-02 22:02:51 -08002812 return grp.pmMEData, nil
2813 }
2814 // Data not in cache, try to fetch from kv store.
2815 data := &pmMEData{}
2816 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002817 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2818 return data, fmt.Errorf("pmKvStore not set. device-id - %s", mm.deviceID)
Girish Gowdra0e533642021-03-02 22:02:51 -08002819 }
2820 Value, err := mm.pmKvStore.Get(ctx, groupName)
2821 if err == nil {
2822 if Value != nil {
2823 logger.Debugw(ctx, "PM data read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002824 log.Fields{"Key": Value.Key, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002825 tmpBytes, _ := kvstore.ToByte(Value.Value)
2826
2827 if err = json.Unmarshal(tmpBytes, data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002828 logger.Errorw(ctx, "unable to unmarshal PM data", log.Fields{"error": err, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002829 return data, err
2830 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002831 logger.Debugw(ctx, "PM data", log.Fields{"pmData": data, "groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002832 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002833 logger.Debugw(ctx, "no PM data found", log.Fields{"groupName": groupName, "device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002834 return data, err
2835 }
2836 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002837 logger.Errorw(ctx, "unable to read from KVstore", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002838 return data, err
2839 }
2840
2841 return data, nil
2842}
2843
2844// 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 +00002845func (mm *OnuMetricsManager) updatePmData(ctx context.Context, groupName string, meInstanceID uint16, pmAction string) error {
2846 logger.Debugw(ctx, "updatePmData - start", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "entityID": meInstanceID, "pmAction": pmAction})
2847 mm.OnuMetricsManagerLock.Lock()
2848 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra0e533642021-03-02 22:02:51 -08002849
2850 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002851 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2852 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002853 }
2854
2855 pmMEData, err := mm.getPmData(ctx, groupName)
2856 if err != nil || pmMEData == nil {
2857 // error already logged in called function.
2858 return err
2859 }
2860 switch pmAction {
2861 case cPmAdd:
2862 pmMEData.InstancesToAdd = mm.appendIfMissingUnt16(pmMEData.InstancesToAdd, meInstanceID)
2863 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2864 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2865 case cPmAdded:
2866 pmMEData.InstancesActive = mm.appendIfMissingUnt16(pmMEData.InstancesActive, meInstanceID)
2867 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2868 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2869 case cPmRemove:
2870 pmMEData.InstancesToDelete = mm.appendIfMissingUnt16(pmMEData.InstancesToDelete, meInstanceID)
2871 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2872 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2873 case cPmRemoved:
2874 pmMEData.InstancesToDelete = mm.removeIfFoundUint16(pmMEData.InstancesToDelete, meInstanceID)
2875 pmMEData.InstancesToAdd = mm.removeIfFoundUint16(pmMEData.InstancesToAdd, meInstanceID)
2876 pmMEData.InstancesActive = mm.removeIfFoundUint16(pmMEData.InstancesActive, meInstanceID)
2877 default:
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002878 logger.Errorw(ctx, "unknown pm action", log.Fields{"device-id": mm.deviceID, "pmAction": pmAction, "groupName": groupName})
2879 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 -08002880 }
2881 // write through cache
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002882 mm.GroupMetricMap[groupName].pmMEData = pmMEData
Girish Gowdra0e533642021-03-02 22:02:51 -08002883
2884 Value, err := json.Marshal(*pmMEData)
2885 if err != nil {
2886 logger.Errorw(ctx, "unable to marshal PM data", log.Fields{"groupName": groupName, "pmAction": pmAction, "pmData": *pmMEData, "err": err})
2887 return err
2888 }
2889 // Update back to kv store
2890 if err = mm.pmKvStore.Put(ctx, groupName, Value); err != nil {
2891 logger.Errorw(ctx, "unable to put PM data to kv store", log.Fields{"groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction, "err": err})
2892 return err
2893 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002894 logger.Debugw(ctx, "updatePmData - success", log.Fields{"device-id": mm.deviceID, "groupName": groupName, "pmData": *pmMEData, "pmAction": pmAction})
Girish Gowdra0e533642021-03-02 22:02:51 -08002895
2896 return nil
2897}
2898
2899// clearPmGroupData cleans PM Group data from store
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002900func (mm *OnuMetricsManager) clearPmGroupData(ctx context.Context) error {
2901 mm.OnuMetricsManagerLock.Lock()
2902 defer mm.OnuMetricsManagerLock.Unlock()
2903 logger.Debugw(ctx, "clearPmGroupData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002904 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002905 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2906 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002907 }
2908
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002909 for n := range mm.GroupMetricMap {
Girish Gowdra0e533642021-03-02 22:02:51 -08002910 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002911 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Girish Gowdra0e533642021-03-02 22:02:51 -08002912 // do not abort this procedure. continue to delete next group.
2913 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002914 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Girish Gowdra0e533642021-03-02 22:02:51 -08002915 }
2916 }
2917
2918 return nil
2919}
2920
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002921// ClearAllPmData clears all PM data associated with the device from KV store
2922func (mm *OnuMetricsManager) ClearAllPmData(ctx context.Context) error {
2923 mm.OnuMetricsManagerLock.Lock()
2924 defer mm.OnuMetricsManagerLock.Unlock()
2925 logger.Debugw(ctx, "ClearAllPmData - start", log.Fields{"device-id": mm.deviceID})
Girish Gowdra0e533642021-03-02 22:02:51 -08002926 if mm.pmKvStore == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002927 logger.Errorw(ctx, "pmKvStore not set - abort", log.Fields{"device-id": mm.deviceID})
2928 return fmt.Errorf(fmt.Sprintf("pmKvStore-not-set-abort-%s", mm.deviceID))
Girish Gowdra0e533642021-03-02 22:02:51 -08002929 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002930 var value error
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002931 for n := range mm.GroupMetricMap {
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002932 if err := mm.pmKvStore.Delete(ctx, n); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002933 logger.Errorw(ctx, "clearPmGroupData - fail", log.Fields{"deviceID": mm.deviceID, "groupName": n, "err": err})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002934 value = err
2935 // do not abort this procedure - continue to delete next group.
2936 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002937 logger.Debugw(ctx, "clearPmGroupData - success", log.Fields{"device-id": mm.deviceID, "groupName": n})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002938 }
Girish Gowdra0e533642021-03-02 22:02:51 -08002939 }
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002940 if value == nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002941 logger.Debugw(ctx, "ClearAllPmData - success", log.Fields{"device-id": mm.deviceID})
Holger Hildebrandt44a0d4f2021-03-18 14:00:54 +00002942 }
2943 return value
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002944}
2945
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002946func (mm *OnuMetricsManager) updateOmciProcessingStatus(status bool) {
2947 mm.OnuMetricsManagerLock.Lock()
2948 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002949 mm.omciProcessingActive = status
2950}
2951
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002952// updateTickGenerationStatus - TODO: add comment
2953func (mm *OnuMetricsManager) updateTickGenerationStatus(status bool) {
2954 mm.OnuMetricsManagerLock.Lock()
2955 defer mm.OnuMetricsManagerLock.Unlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002956 mm.tickGenerationActive = status
2957}
2958
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002959// GetOmciProcessingStatus - TODO: add comment
2960func (mm *OnuMetricsManager) GetOmciProcessingStatus() bool {
2961 mm.OnuMetricsManagerLock.RLock()
2962 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002963 return mm.omciProcessingActive
2964}
2965
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002966// GetTickGenerationStatus - TODO: add comment
2967func (mm *OnuMetricsManager) GetTickGenerationStatus() bool {
2968 mm.OnuMetricsManagerLock.RLock()
2969 defer mm.OnuMetricsManagerLock.RUnlock()
Girish Gowdra7b0ee5c2021-03-19 21:48:15 -07002970 return mm.tickGenerationActive
2971}
2972
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002973func (mm *OnuMetricsManager) appendIfMissingString(slice []string, n string) []string {
Girish Gowdrae0140f02021-02-02 16:55:09 -08002974 for _, ele := range slice {
2975 if ele == n {
2976 return slice
2977 }
2978 }
2979 return append(slice, n)
2980}
2981
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002982func (mm *OnuMetricsManager) removeIfFoundString(slice []string, n string) []string {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002983 for i, ele := range slice {
2984 if ele == n {
2985 return append(slice[:i], slice[i+1:]...)
2986 }
2987 }
2988 return slice
2989}
2990
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00002991func (mm *OnuMetricsManager) appendIfMissingUnt16(slice []uint16, n uint16) []uint16 {
Girish Gowdra5c5aaf42021-02-17 19:40:50 -08002992 for _, ele := range slice {
2993 if ele == n {
2994 return slice
2995 }
2996 }
2997 return append(slice, n)
2998}
2999
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003000func (mm *OnuMetricsManager) removeIfFoundUint16(slice []uint16, n uint16) []uint16 {
Girish Gowdrae0140f02021-02-02 16:55:09 -08003001 for i, ele := range slice {
3002 if ele == n {
3003 return append(slice[:i], slice[i+1:]...)
3004 }
3005 }
3006 return slice
Girish Gowdrae09a6202021-01-12 18:10:59 -08003007}
Himani Chawla43f95ff2021-06-03 00:24:12 +05303008
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003009func (mm *OnuMetricsManager) getEthernetFrameExtendedMETypeFromKvStore(ctx context.Context) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303010 // Check if the data is already available in KV store, if yes, do not send the request for get me.
3011 var data me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003012 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3013 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3014 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303015 Value, err := mm.extPmKvStore.Get(ctx, key)
3016 if err == nil {
3017 if Value != nil {
3018 logger.Debugw(ctx, "me-type-read",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003019 log.Fields{"key": Value.Key, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303020 tmpBytes, _ := kvstore.ToByte(Value.Value)
3021
3022 if err = json.Unmarshal(tmpBytes, &data); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003023 logger.Errorw(ctx, "unable-to-unmarshal-data", log.Fields{"error": err, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303024 return false, err
3025 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003026 logger.Debugw(ctx, "me-ext-pm-class-data", log.Fields{"class-id": data, "device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303027 // We have found the data from db, no need to get through omci get message.
3028 mm.supportedEthernetFrameExtendedPMClass = data
3029 return true, nil
3030 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003031 logger.Debugw(ctx, "no-me-ext-pm-class-data-found", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303032 return false, nil
3033 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003034 logger.Errorw(ctx, "unable-to-read-from-kv-store", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303035 return false, err
3036}
3037
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003038func (mm *OnuMetricsManager) waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx context.Context, create bool, instID uint16, meClassID me.ClassID, upstream bool) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303039 logger.Debugw(ctx, "wait-for-ethernet-frame-create-or-delete-response-or-timeout", log.Fields{"create": create, "instID": instID, "meClassID": meClassID})
3040 select {
Himani Chawlaee10b542021-09-20 16:46:40 +05303041 case resp := <-mm.extendedPMMeResponseChan:
Himani Chawla43f95ff2021-06-03 00:24:12 +05303042 logger.Debugw(ctx, "received-extended-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003043 log.Fields{"device-id": mm.deviceID, "resp": resp, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303044 // If the result is me.InstanceExists it means the entity was already created. It is ok handled that as success
3045 if resp == me.Success || resp == me.InstanceExists {
3046 return true, nil
3047 } else if resp == me.UnknownEntity || resp == me.ParameterError ||
3048 resp == me.ProcessingError || resp == me.NotSupported || resp == me.AttributeFailure {
3049 return false, fmt.Errorf("not-supported-me--resp-code-%v", resp)
3050 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003051 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 +05303052 return true, fmt.Errorf("error-while-creating-me--resp-code-%v", resp)
3053 }
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003054 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303055 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-response",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003056 log.Fields{"device-id": mm.deviceID, "resp": false, "create": create, "meClassID": meClassID, "instID": instID, "upstream": upstream})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303057 }
3058 return false, fmt.Errorf("timeout-while-waiting-for-response")
3059}
3060
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003061func (mm *OnuMetricsManager) tryCreateExtPmMe(ctx context.Context, meType me.ClassID) (bool, error) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303062 cnt := 0
Himani Chawla43f95ff2021-06-03 00:24:12 +05303063 // 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 +05303064 for _, direction := range []bool{true, false} {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003065 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303066 var entityID uint16
3067 if direction {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003068 entityID = uniPort.EntityID + 0x100
Himani Chawla43f95ff2021-06-03 00:24:12 +05303069 } else {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003070 entityID = uniPort.EntityID
Himani Chawla43f95ff2021-06-03 00:24:12 +05303071 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303072 logger.Debugw(ctx, "try-creating-extended-pm-me", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303073 // parent entity id will be same for both direction
Himani Chawlaee10b542021-09-20 16:46:40 +05303074 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, direction, uniPort.EntityID, false)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303075
3076 inner1:
3077 // retry ExtendedPmCreateAttempts times to create the instance of PM
3078 for cnt = 0; cnt < ExtendedPmCreateAttempts; cnt++ {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003079 meEnt, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendCreateOrDeleteEthernetFrameExtendedPMME(
3080 ctx, mm.pDeviceHandler.GetOmciTimeout(), true, direction, true,
3081 mm.PAdaptFsm.CommChan, entityID, meType, controlBlock)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303082 if err != nil {
3083 logger.Errorw(ctx, "EthernetFrameExtendedPMME-create-or-delete-failed",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003084 log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303085 return false, err
3086 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303087 if supported, err := mm.waitForEthernetFrameCreateOrDeleteResponseOrTimeout(ctx, true, entityID,
3088 meType, direction); err == nil && supported {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303089 if direction {
Himani Chawlac77d5372021-07-12 15:42:26 +05303090 mm.ethernetFrameExtendedPmUpStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303091 } else {
Himani Chawlac77d5372021-07-12 15:42:26 +05303092 mm.ethernetFrameExtendedPmDownStreamMEByEntityID[entityID] = meEnt
Himani Chawla43f95ff2021-06-03 00:24:12 +05303093 }
3094 break inner1
3095 } else if err != nil {
3096 if !supported {
3097 // Need to return immediately
3098 return false, err
3099 }
3100 //In case of failure, go for a retry
3101 }
3102 }
3103 if cnt == ExtendedPmCreateAttempts {
3104 logger.Error(ctx, "exceeded-attempts-while-creating-me-for-ethernet-frame-extended-pm")
3105 return true, fmt.Errorf("unable-to-create-me")
3106 }
3107 }
3108 }
3109 return true, nil
3110}
3111
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003112func (mm *OnuMetricsManager) putExtPmMeKvStore(ctx context.Context) {
3113 key := fmt.Sprintf("%s/%s/%s", mm.pOnuDeviceEntry.GetPersVendorID(),
3114 mm.pOnuDeviceEntry.GetPersEquipmentID(),
3115 mm.pOnuDeviceEntry.GetPersActiveSwVersion())
Himani Chawla43f95ff2021-06-03 00:24:12 +05303116 // check if we get the supported type me for ethernet frame extended pm class id
3117 if mm.supportedEthernetFrameExtendedPMClass == 0 {
3118 logger.Error(ctx, "unable-to-get-any-supported-extended-pm-me-class")
3119 }
3120 classSupported, err := json.Marshal(mm.supportedEthernetFrameExtendedPMClass)
3121 if err != nil {
3122 logger.Errorw(ctx, "unable-to-marshal-data", log.Fields{"err": err})
3123 }
3124 if err := mm.extPmKvStore.Put(ctx, key, classSupported); err != nil {
3125 logger.Errorw(ctx, "unable-to-add-data-in-db", log.Fields{"err": err})
3126 }
3127}
3128
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003129func (mm *OnuMetricsManager) setAllExtPmMeCreatedFlag() {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303130 mm.onuEthernetFrameExtendedPmLock.Lock()
3131 mm.isDeviceReadyToCollectExtendedPmStats = true
3132 mm.onuEthernetFrameExtendedPmLock.Unlock()
3133}
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003134
Himani Chawlaee10b542021-09-20 16:46:40 +05303135// CreateEthernetFrameExtendedPMME - This method tries to create the possible me type for extended pms
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003136func (mm *OnuMetricsManager) CreateEthernetFrameExtendedPMME(ctx context.Context) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303137 //get the type of extended frame pm me supported by onu first
3138 exist, err := mm.getEthernetFrameExtendedMETypeFromKvStore(ctx)
3139 if err != nil {
3140 logger.Error(ctx, "unable-to-get-supported-me-for-ethernet-frame-extended-pm")
3141 return
3142 }
3143 if exist {
3144 // we have the me type, go ahead with the me type supported.
3145 if _, err := mm.tryCreateExtPmMe(ctx, mm.supportedEthernetFrameExtendedPMClass); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003146 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303147 "meClassID": mm.supportedEthernetFrameExtendedPMClass})
3148 return
3149 }
3150 mm.setAllExtPmMeCreatedFlag()
3151 return
3152 }
3153 // First try with 64 bit me
3154 // we have the me type, go ahead with the me type supported.
3155 supported64Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPm64BitClassID)
3156 if err != nil && !supported64Bit {
3157 logger.Errorw(ctx, "unable-to-create-me-type-as-it-is-not-supported",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003158 log.Fields{"device-id": mm.deviceID, "meClassID": me.EthernetFrameExtendedPm64BitClassID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303159 "supported": supported64Bit})
3160 // Then Try with 32 bit type
3161 if supported32Bit, err := mm.tryCreateExtPmMe(ctx, me.EthernetFrameExtendedPmClassID); err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003162 logger.Errorw(ctx, "unable-to-create-me-type", log.Fields{"device-id": mm.deviceID,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303163 "meClassID": me.EthernetFrameExtendedPmClassID, "supported": supported32Bit})
3164 } else if supported32Bit {
3165 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPmClassID
3166 mm.putExtPmMeKvStore(ctx)
3167 mm.setAllExtPmMeCreatedFlag()
3168 }
3169 } else if err == nil && supported64Bit {
3170 mm.supportedEthernetFrameExtendedPMClass = me.EthernetFrameExtendedPm64BitClassID
3171 mm.putExtPmMeKvStore(ctx)
3172 mm.setAllExtPmMeCreatedFlag()
3173 }
3174}
3175
Himani Chawlaee10b542021-09-20 16:46:40 +05303176func (mm *OnuMetricsManager) setControlBlockResetFlagForEthernetExtendedPMME(ctx context.Context, upstream bool,
3177 entityID uint16, meName string, reset bool) (extension.GetValueResponse_ErrorReason, error) {
3178 uniPortEntityID := entityID
3179 if upstream {
3180 uniPortEntityID = entityID - 0x100
3181 }
3182 controlBlock := mm.getControlBlockForExtendedPMDirection(ctx, upstream, uniPortEntityID, reset)
3183 _, err := mm.pOnuDeviceEntry.GetDevOmciCC().SendSetEthernetFrameExtendedPMME(ctx,
3184 mm.pDeviceHandler.GetOmciTimeout(), true,
3185 mm.PAdaptFsm.CommChan, entityID, mm.supportedEthernetFrameExtendedPMClass, controlBlock)
3186 if err != nil {
3187 logger.Errorw(ctx, "EthernetFrameExtendedPMME-set-reset-bit-failed",
3188 log.Fields{"device-id": mm.deviceID})
3189 return extension.GetValueResponse_INTERNAL_ERROR, err
3190 }
3191
3192 if resp := mm.waitForResetResponseOrTimeout(ctx, entityID, meName); resp {
3193 return extension.GetValueResponse_REASON_UNDEFINED, nil
3194 }
3195 return extension.GetValueResponse_INTERNAL_ERROR, fmt.Errorf("unable-to-reset-pm-counters")
3196}
3197
3198func (mm *OnuMetricsManager) waitForResetResponseOrTimeout(ctx context.Context, instID uint16, meClassName string) bool {
3199 logger.Debugw(ctx, "wait-for-ethernet-frame-reset-counters-response-or-timeout", log.Fields{"instID": instID, "meClassName": meClassName})
3200 select {
3201 case resp := <-mm.extendedPMMeResponseChan:
3202 logger.Debugw(ctx, "received-extended-pm-me-reset-response",
3203 log.Fields{"device-id": mm.deviceID, "resp": resp, "meClassName": meClassName, "instID": instID})
3204 if resp == me.Success {
3205 return true
3206 }
3207 return false
3208 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
3209 logger.Errorw(ctx, "timeout-waiting-for-ext-pm-me-reset-response",
3210 log.Fields{"device-id": mm.deviceID, "resp": false, "meClassName": meClassName, "instID": instID})
3211 }
3212 return false
3213}
3214
3215func (mm *OnuMetricsManager) resetEthernetFrameExtendedPMCounters(ctx context.Context,
3216 upstreamEntityMap map[uint16]*me.ManagedEntity, downstreamEntityMap map[uint16]*me.ManagedEntity) (extension.GetValueResponse_ErrorReason, error) {
3217 className := "EthernetFrameExtendedPm64Bit"
3218 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3219 className = "EthernetFrameExtendedPm"
3220 }
3221 // Reset the counters if option is specified
3222 for entityID := range upstreamEntityMap {
3223 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3224 true)
3225 if err != nil {
3226 return errReason, err
3227 }
3228 }
3229
3230 for entityID := range downstreamEntityMap {
3231 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3232 true)
3233 if err != nil {
3234 return errReason, err
3235 }
3236 }
3237 // This is currently done as a workaround for sercomm glasfaser onu as the reset bit is not getting cleared by the
3238 // device itself.
3239 // Unset the reset bit if option is specified
3240 for entityID := range upstreamEntityMap {
3241 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, true, entityID, className,
3242 false)
3243 if err != nil {
3244 return errReason, err
3245 }
3246 }
3247
3248 for entityID := range downstreamEntityMap {
3249 errReason, err := mm.setControlBlockResetFlagForEthernetExtendedPMME(ctx, false, entityID, className,
3250 false)
3251 if err != nil {
3252 return errReason, err
3253 }
3254 }
3255 return extension.GetValueResponse_REASON_UNDEFINED, nil
3256}
3257
3258func (mm *OnuMetricsManager) setEthernetFrameExtendedPmCounterOperationFlag(val bool) {
3259 mm.onuEthernetFrameExtendedPmLock.Lock()
3260 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3261 mm.isEthernetFrameExtendedPmOperationOngoing = val
3262}
3263
3264func (mm *OnuMetricsManager) getEthernetFrameExtendedPmCounterOperationFlag() bool {
3265 mm.onuEthernetFrameExtendedPmLock.Lock()
3266 defer mm.onuEthernetFrameExtendedPmLock.Unlock()
3267 return mm.isEthernetFrameExtendedPmOperationOngoing
3268}
3269
3270// CollectEthernetFrameExtendedPMCounters - This method collects the ethernet frame extended pm counters from the device
3271func (mm *OnuMetricsManager) CollectEthernetFrameExtendedPMCounters(ctx context.Context,
3272 onuInfo *extension.GetOmciEthernetFrameExtendedPmRequest) *extension.SingleGetValueResponse {
3273 errFunc := func(reason extension.GetValueResponse_ErrorReason, err string) *extension.SingleGetValueResponse {
3274 logger.Error(ctx, err)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303275 return &extension.SingleGetValueResponse{
3276 Response: &extension.GetValueResponse{
3277 Status: extension.GetValueResponse_ERROR,
3278 ErrReason: reason,
3279 },
3280 }
3281 }
3282 mm.onuEthernetFrameExtendedPmLock.RLock()
3283 if !mm.isDeviceReadyToCollectExtendedPmStats {
3284 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303285 return errFunc(extension.GetValueResponse_INTERNAL_ERROR, fmt.Sprintf("onu-%v-not-ready-to-collect-stats", mm.deviceID))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303286 }
3287 mm.onuEthernetFrameExtendedPmLock.RUnlock()
Himani Chawlaee10b542021-09-20 16:46:40 +05303288
3289 if mm.getEthernetFrameExtendedPmCounterOperationFlag() {
3290 return errFunc(extension.GetValueResponse_INTERNAL_ERROR,
3291 fmt.Sprintf("extended-pm-reset-or-get-operation-is-still-going-on-for-onu-%v", mm.deviceID))
3292 }
3293 mm.setEthernetFrameExtendedPmCounterOperationFlag(true)
3294 defer mm.setEthernetFrameExtendedPmCounterOperationFlag(false)
3295
3296 upstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3297 downstreamEntityMap := make(map[uint16]*me.ManagedEntity)
3298 if onuInfo.IsUniIndex != nil {
3299 for _, uniPort := range *mm.pDeviceHandler.GetUniEntityMap() {
3300 if uniPort.UniID == uint8(onuInfo.GetUniIndex()) {
3301 logger.Debugw(ctx, "mapped-uni-index-to-uni-port", log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3302 upstreamEntityMap[uniPort.EntityID+0x100] = mm.ethernetFrameExtendedPmUpStreamMEByEntityID[uniPort.EntityID+0x100]
3303 downstreamEntityMap[uniPort.EntityID] = mm.ethernetFrameExtendedPmDownStreamMEByEntityID[uniPort.EntityID]
3304 break
3305 }
3306 }
3307 if len(downstreamEntityMap) == 0 {
3308 logger.Errorw(ctx, "invalid-uni-index-provided-while-fetching-the-extended-pm",
3309 log.Fields{"device-id": mm.deviceID, "uni-index": onuInfo.GetUniIndex()})
3310 return errFunc(extension.GetValueResponse_INVALID_REQ_TYPE,
3311 fmt.Sprintf("onu-%s-invalid-uni-%v", mm.deviceID, onuInfo.GetUniIndex()))
3312 }
3313 } else {
3314 // make a copy of all downstream and upstream maps in the local ones
3315 for entityID, meEnt := range mm.ethernetFrameExtendedPmUpStreamMEByEntityID {
3316 upstreamEntityMap[entityID] = meEnt
3317 }
3318 for entityID, meEnt := range mm.ethernetFrameExtendedPmDownStreamMEByEntityID {
3319 downstreamEntityMap[entityID] = meEnt
3320 }
3321 }
3322 logger.Debugw(ctx, "extended-pm-collection-me-count", log.Fields{"device-id": mm.deviceID,
3323 "count": len(upstreamEntityMap) + len(downstreamEntityMap)})
3324 // Reset the metrics first for all required me's
3325 if onuInfo.Reset_ {
3326 errReason, err := mm.resetEthernetFrameExtendedPMCounters(ctx, upstreamEntityMap, downstreamEntityMap)
3327 if err != nil {
3328 logger.Errorw(ctx, "unable-to-reset-ethernet-frame-extended-pm-counters",
3329 log.Fields{"device-id": mm.deviceID})
3330 return errFunc(errReason, fmt.Sprintf("%v", err.Error()))
3331 }
3332 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303333 // Collect metrics for upstream for all the PM Mes per uni port and aggregate
3334 var pmUpstream extension.OmciEthernetFrameExtendedPm
3335 var pmDownstream extension.OmciEthernetFrameExtendedPm
Himani Chawla89ea9e62021-08-25 17:01:03 +05303336 counterFormat := extension.GetOmciEthernetFrameExtendedPmResponse_SIXTY_FOUR_BIT
3337 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3338 counterFormat = extension.GetOmciEthernetFrameExtendedPmResponse_THIRTY_TWO_BIT
3339 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303340 if !onuInfo.Reset_ {
3341 for entityID, meEnt := range upstreamEntityMap {
3342 logger.Debugw(ctx, "collect-upstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3343 var receivedMask uint16
3344 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, true, &receivedMask); metricInfo != nil { // upstream
3345 if receivedMask == 0 {
3346 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, false)
Himani Chawlae18b10f2021-10-27 11:51:47 +05303347 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-upstream-are-unsupported")
3348 // It might be possible that still some downstream pms are supported and hence we need to continue
3349 // further to collect the downstream stats but stop collecting upstream stats for other ME's.
3350 break
Himani Chawla43f95ff2021-06-03 00:24:12 +05303351 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303352 // Aggregate the result for upstream
3353 pmUpstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmUpstream, true)
3354 } else {
3355 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
Himani Chawla43f95ff2021-06-03 00:24:12 +05303356 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303357 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303358
Himani Chawlaee10b542021-09-20 16:46:40 +05303359 for entityID, meEnt := range downstreamEntityMap {
3360 logger.Debugw(ctx, "collect-downstream-pm-counters-for-entity-id", log.Fields{"device-id": mm.deviceID, "entityID": entityID})
3361 var receivedMask uint16
3362 if metricInfo, errResp, err := mm.collectEthernetFrameExtendedPMData(ctx, meEnt, entityID, false, &receivedMask); metricInfo != nil { // downstream
Himani Chawlae18b10f2021-10-27 11:51:47 +05303363 if receivedMask == 0 {
3364 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, false)
3365 logger.Error(ctx, "all-the-attributes-of-ethernet-frame-extended-pm-counters-for-downstream-are-unsupported")
3366 // Stop collecting downstream counters for other ME's.
3367 break
3368 }
Himani Chawlaee10b542021-09-20 16:46:40 +05303369 // Aggregate the result for downstream
3370 pmDownstream = mm.aggregateEthernetFrameExtendedPM(metricInfo, pmDownstream, true)
3371 } else {
3372 return errFunc(errResp, fmt.Sprintf("%v", err.Error()))
3373 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303374 }
3375 }
3376 singleValResp := extension.SingleGetValueResponse{
3377 Response: &extension.GetValueResponse{
3378 Status: extension.GetValueResponse_OK,
3379 Response: &extension.GetValueResponse_OnuCounters{
3380 OnuCounters: &extension.GetOmciEthernetFrameExtendedPmResponse{
Himani Chawla89ea9e62021-08-25 17:01:03 +05303381 Upstream: &pmUpstream,
3382 Downstream: &pmDownstream,
3383 OmciEthernetFrameExtendedPmFormat: counterFormat,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303384 },
3385 },
3386 },
3387 }
3388 return &singleValResp
3389}
3390
Himani Chawlaee10b542021-09-20 16:46:40 +05303391func (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 +05303392 var classID me.ClassID
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003393 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 +05303394
3395 classID = mm.supportedEthernetFrameExtendedPMClass
3396 attributeMaskList := maskToEthernetFrameExtendedPM64Bit
3397 if classID == me.EthernetFrameExtendedPmClassID {
3398 attributeMaskList = maskToEthernetFrameExtendedPM32Bit
3399 }
3400 ethPMData := make(map[string]uint64)
3401 var sumReceivedMask uint16
3402 for mask := range attributeMaskList {
3403 if errResp, err := mm.populateEthernetFrameExtendedPMMetrics(ctx, classID, entityID, mask, ethPMData, upstream, &sumReceivedMask); err != nil {
3404 logger.Errorw(ctx, "error-during-metric-collection",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003405 log.Fields{"device-id": mm.deviceID, "entityID": entityID, "err": err})
Himani Chawlaee10b542021-09-20 16:46:40 +05303406 return nil, errResp, err
Himani Chawla43f95ff2021-06-03 00:24:12 +05303407 }
3408 if (mask == 0x3F00 || mask == 0x3800) && sumReceivedMask == 0 {
3409 //It means the first attributes fetch was a failure, hence instead of sending multiple failure get requests
3410 //populate all counters as failure and return
3411 mm.fillAllErrorCountersEthernetFrameExtendedPM(ethPMData)
3412 break
3413 }
3414 }
3415 *receivedMask = sumReceivedMask
Himani Chawlaee10b542021-09-20 16:46:40 +05303416 return ethPMData, extension.GetValueResponse_REASON_UNDEFINED, nil
Himani Chawla43f95ff2021-06-03 00:24:12 +05303417}
3418
3419// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003420func (mm *OnuMetricsManager) populateEthernetFrameExtendedPMMetrics(ctx context.Context, classID me.ClassID, entityID uint16,
Himani Chawla43f95ff2021-06-03 00:24:12 +05303421 requestedAttributesMask uint16, ethFrameExtPMData map[string]uint64, upstream bool, sumReceivedMask *uint16) (extension.GetValueResponse_ErrorReason, error) {
3422 var meAttributes me.AttributeValueMap
3423 logger.Debugw(ctx, "requesting-attributes", log.Fields{"attributes-mask": requestedAttributesMask, "entityID": entityID, "classID": classID})
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003424 err := mm.pOnuDeviceEntry.GetDevOmciCC().SendGetMeWithAttributeMask(ctx, classID, entityID, requestedAttributesMask, mm.pDeviceHandler.GetOmciTimeout(), true, mm.PAdaptFsm.CommChan)
Himani Chawla43f95ff2021-06-03 00:24:12 +05303425 if err != nil {
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003426 logger.Errorw(ctx, "get-me-failed", log.Fields{"device-id": mm.deviceID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303427 return extension.GetValueResponse_INTERNAL_ERROR, err
3428 }
3429 select {
3430 case meAttributes = <-mm.extendedPmMeChan:
3431 logger.Debugw(ctx, "received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003432 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
3433 case <-time.After(mm.pOnuDeviceEntry.GetDevOmciCC().GetMaxOmciTimeoutWithRetries() * time.Second):
Himani Chawla43f95ff2021-06-03 00:24:12 +05303434 logger.Errorw(ctx, "timeout-waiting-for-omci-get-response-for-received-extended-pm-data",
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003435 log.Fields{"device-id": mm.deviceID, "upstream": upstream, "entityID": entityID})
Himani Chawla43f95ff2021-06-03 00:24:12 +05303436 return extension.GetValueResponse_TIMEOUT, fmt.Errorf("timeout-waiting-for-omci-get-response-for-received-extended-pm-data")
3437 }
3438 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3439 mask := mm.getEthFrameExtPMDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3440 *sumReceivedMask += mask
3441 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3442 } else {
3443 mask := mm.getEthFrameExtPM64BitDataFromResponse(ctx, ethFrameExtPMData, meAttributes, requestedAttributesMask)
3444 *sumReceivedMask += mask
3445 logger.Debugw(ctx, "data-received-for-ethernet-frame-ext-pm", log.Fields{"data": ethFrameExtPMData, "entityID": entityID})
3446 }
3447
3448 return extension.GetValueResponse_REASON_UNDEFINED, nil
3449}
3450
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003451func (mm *OnuMetricsManager) fillAllErrorCountersEthernetFrameExtendedPM(ethFrameExtPMData map[string]uint64) {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303452 sourceMap := maskToEthernetFrameExtendedPM64Bit
3453 errorCounterValue := UnsupportedCounterValue64bit
3454 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3455 sourceMap = maskToEthernetFrameExtendedPM32Bit
3456 errorCounterValue = UnsupportedCounterValue32bit
3457 }
3458 for _, value := range sourceMap {
3459 for _, k := range value {
3460 if _, ok := ethFrameExtPMData[k]; !ok {
3461 ethFrameExtPMData[k] = errorCounterValue
3462 }
3463 }
3464 }
3465}
3466
3467// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003468func (mm *OnuMetricsManager) getEthFrameExtPMDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303469 receivedMask := uint16(0)
3470 switch requestedAttributesMask {
3471 case 0x3F00:
3472 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3473 if _, ok := ethFrameExtPMData[k]; !ok {
3474 switch k {
3475 case "drop_events":
3476 if val, ok := meAttributes[dropEvents]; ok && val != nil {
3477 ethFrameExtPMData[k] = uint64(val.(uint32))
3478 receivedMask |= 0x2000
3479 } else if !ok {
3480 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3481 }
3482 case "octets":
3483 if val, ok := meAttributes[octets]; ok && val != nil {
3484 ethFrameExtPMData[k] = uint64(val.(uint32))
3485 receivedMask |= 0x1000
3486 } else if !ok {
3487 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3488 }
3489 case "frames":
3490 if val, ok := meAttributes[frames]; ok && val != nil {
3491 ethFrameExtPMData[k] = uint64(val.(uint32))
3492 receivedMask |= 0x800
3493 } else if !ok {
3494 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3495 }
3496 case "broadcast_frames":
3497 if val, ok := meAttributes[broadcastFrames]; ok && val != nil {
3498 ethFrameExtPMData[k] = uint64(val.(uint32))
3499 receivedMask |= 0x400
3500 } else if !ok {
3501 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3502 }
3503 case "multicast_frames":
3504 if val, ok := meAttributes[multicastFrames]; ok && val != nil {
3505 ethFrameExtPMData[k] = uint64(val.(uint32))
3506 receivedMask |= 0x200
3507 } else if !ok {
3508 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3509 }
3510 case "crc_errored_frames":
3511 if val, ok := meAttributes[crcErroredFrames]; ok && val != nil {
3512 ethFrameExtPMData[k] = uint64(val.(uint32))
3513 receivedMask |= 0x100
3514 } else if !ok {
3515 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3516 }
3517 default:
3518 //do nothing
3519 }
3520 }
3521 }
3522 case 0x00FC:
3523 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3524 if _, ok := ethFrameExtPMData[k]; !ok {
3525 switch k {
3526 case "undersize_frames":
3527 if val, ok := meAttributes[undersizeFrames]; ok && val != nil {
3528 ethFrameExtPMData[k] = uint64(val.(uint32))
3529 receivedMask |= 0x80
3530 } else if !ok {
3531 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3532 }
3533 case "oversize_frames":
3534 if val, ok := meAttributes[oversizeFrames]; ok && val != nil {
3535 ethFrameExtPMData[k] = uint64(val.(uint32))
3536 receivedMask |= 0x40
3537 } else if !ok {
3538 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3539 }
3540 case "64_octets":
3541 if val, ok := meAttributes[frames64Octets]; ok && val != nil {
3542 ethFrameExtPMData[k] = uint64(val.(uint32))
3543 receivedMask |= 0x20
3544 } else if !ok {
3545 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3546 }
3547 case "65_to_127_octets":
3548 if val, ok := meAttributes[frames65To127Octets]; ok && val != nil {
3549 ethFrameExtPMData[k] = uint64(val.(uint32))
3550 receivedMask |= 0x10
3551 } else if !ok {
3552 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3553 }
3554 case "128_to_255_octets":
3555 if val, ok := meAttributes[frames128To255Octets]; ok && val != nil {
3556 ethFrameExtPMData[k] = uint64(val.(uint32))
3557 receivedMask |= 0x8
3558 } else if !ok {
3559 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3560 }
3561 case "256_to_511_octets":
3562 if val, ok := meAttributes[frames256To511Octets]; ok && val != nil {
3563 ethFrameExtPMData[k] = uint64(val.(uint32))
3564 receivedMask |= 0x4
3565 } else if !ok {
3566 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3567 }
3568 default:
3569 //do nothing
3570 }
3571 }
3572 }
3573 case 0x0003:
3574 for _, k := range maskToEthernetFrameExtendedPM32Bit[requestedAttributesMask] {
3575 if _, ok := ethFrameExtPMData[k]; !ok {
3576 switch k {
3577 case "512_to_1023_octets":
3578 if val, ok := meAttributes[frames512To1023Octets]; ok && val != nil {
3579 ethFrameExtPMData[k] = uint64(val.(uint32))
3580 receivedMask |= 0x2
3581 } else if !ok {
3582 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3583 }
3584 case "1024_to_1518_octets":
3585 if val, ok := meAttributes[frames1024To1518Octets]; ok && val != nil {
3586 ethFrameExtPMData[k] = uint64(val.(uint32))
3587 receivedMask |= 0x1
3588 } else if !ok {
3589 ethFrameExtPMData[k] = UnsupportedCounterValue32bit
3590 }
3591 default:
3592 //do nothing
3593 }
3594 }
3595 }
3596 default:
3597 //do nothing
3598 }
3599 return receivedMask
3600}
3601
3602// nolint: gocyclo
Holger Hildebrandt4b5e73f2021-08-19 06:51:21 +00003603func (mm *OnuMetricsManager) getEthFrameExtPM64BitDataFromResponse(ctx context.Context, ethFrameExtPMData map[string]uint64, meAttributes me.AttributeValueMap, requestedAttributesMask uint16) uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303604 receivedMask := uint16(0)
3605 switch requestedAttributesMask {
3606 case 0x3800:
3607 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3608 if _, ok := ethFrameExtPMData[k]; !ok {
3609 switch k {
3610 case "drop_events":
3611 if val, ok := meAttributes[dropEvents]; ok && val != nil {
3612 ethFrameExtPMData[k] = val.(uint64)
3613 receivedMask |= 0x2000
3614 } else if !ok {
3615 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3616 }
3617 case "octets":
3618 if val, ok := meAttributes[octets]; ok && val != nil {
3619 ethFrameExtPMData[k] = val.(uint64)
3620 receivedMask |= 0x1000
3621 } else if !ok {
3622 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3623 }
3624 case "frames":
3625 if val, ok := meAttributes[frames]; ok && val != nil {
3626 ethFrameExtPMData[k] = val.(uint64)
3627 receivedMask |= 0x800
3628 } else if !ok {
3629 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3630 }
3631 }
3632 }
3633 }
3634 case 0x0700:
3635 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3636 if _, ok := ethFrameExtPMData[k]; !ok {
3637 switch k {
3638 case "broadcast_frames":
3639 if val, ok := meAttributes[broadcastFrames]; ok && val != nil {
3640 ethFrameExtPMData[k] = val.(uint64)
3641 receivedMask |= 0x400
3642 } else if !ok {
3643 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3644 }
3645 case "multicast_frames":
3646 if val, ok := meAttributes[multicastFrames]; ok && val != nil {
3647 ethFrameExtPMData[k] = val.(uint64)
3648 receivedMask |= 0x200
3649 } else if !ok {
3650 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3651 }
3652 case "crc_errored_frames":
3653 if val, ok := meAttributes[crcErroredFrames]; ok && val != nil {
3654 ethFrameExtPMData[k] = val.(uint64)
3655 receivedMask |= 0x100
3656 } else if !ok {
3657 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3658 }
3659 }
3660 }
3661 }
3662 case 0x00E0:
3663 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3664 if _, ok := ethFrameExtPMData[k]; !ok {
3665 switch k {
3666 case "undersize_frames":
3667 if val, ok := meAttributes[undersizeFrames]; ok && val != nil {
3668 ethFrameExtPMData[k] = val.(uint64)
3669 receivedMask |= 0x80
3670 } else if !ok {
3671 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3672 }
3673 case "oversize_frames":
3674 if val, ok := meAttributes[oversizeFrames]; ok && val != nil {
3675 ethFrameExtPMData[k] = val.(uint64)
3676 receivedMask |= 0x40
3677 } else if !ok {
3678 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3679 }
3680 case "64_octets":
3681 if val, ok := meAttributes[frames64Octets]; ok && val != nil {
3682 ethFrameExtPMData[k] = val.(uint64)
3683 receivedMask |= 0x20
3684 } else if !ok {
3685 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3686 }
3687 }
3688 }
3689 }
3690 case 0x001C:
3691 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3692 if _, ok := ethFrameExtPMData[k]; !ok {
3693 switch k {
3694 case "65_to_127_octets":
3695 if val, ok := meAttributes[frames65To127Octets]; ok && val != nil {
3696 ethFrameExtPMData[k] = val.(uint64)
3697 receivedMask |= 0x10
3698 } else if !ok {
3699 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3700 }
3701 case "128_to_255_octets":
3702 if val, ok := meAttributes[frames128To255Octets]; ok && val != nil {
3703 ethFrameExtPMData[k] = val.(uint64)
3704 receivedMask |= 0x8
3705 } else if !ok {
3706 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3707 }
3708 case "256_to_511_octets":
3709 if val, ok := meAttributes[frames256To511Octets]; ok && val != nil {
3710 ethFrameExtPMData[k] = val.(uint64)
3711 receivedMask |= 0x4
3712 } else if !ok {
3713 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3714 }
3715 default:
3716 //do nothing
3717 }
3718 }
3719 }
3720 case 0x0003:
3721 for _, k := range maskToEthernetFrameExtendedPM64Bit[requestedAttributesMask] {
3722 if _, ok := ethFrameExtPMData[k]; !ok {
3723 switch k {
3724 case "512_to_1023_octets":
3725 if val, ok := meAttributes[frames512To1023Octets]; ok && val != nil {
3726 ethFrameExtPMData[k] = val.(uint64)
3727 receivedMask |= 0x2
3728 } else if !ok {
3729 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3730 }
3731 case "1024_to_1518_octets":
3732 if val, ok := meAttributes[frames1024To1518Octets]; ok && val != nil {
3733 ethFrameExtPMData[k] = val.(uint64)
3734 receivedMask |= 0x1
3735 } else if !ok {
3736 ethFrameExtPMData[k] = UnsupportedCounterValue64bit
3737 }
3738 default:
3739 //do nothing
3740 }
3741 }
3742 }
3743 }
3744 return receivedMask
3745}
3746
Himani Chawlaee10b542021-09-20 16:46:40 +05303747func (mm *OnuMetricsManager) aggregateEthernetFrameExtendedPM(pmDataIn map[string]uint64,
3748 pmData extension.OmciEthernetFrameExtendedPm, aggregate bool) extension.OmciEthernetFrameExtendedPm {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303749 errorCounterValue := UnsupportedCounterValue64bit
3750 if mm.supportedEthernetFrameExtendedPMClass == me.EthernetFrameExtendedPmClassID {
3751 errorCounterValue = UnsupportedCounterValue32bit
3752 }
3753 var pmDataOut extension.OmciEthernetFrameExtendedPm
3754 if aggregate {
3755 if pmData.DropEvents != errorCounterValue {
3756 pmDataOut.DropEvents = pmData.DropEvents + pmDataIn["drop_events"]
3757 } else {
3758 pmDataOut.DropEvents = pmData.DropEvents
3759 }
3760 if pmData.Octets != errorCounterValue {
3761 pmDataOut.Octets = pmData.Octets + pmDataIn["octets"]
3762 } else {
3763 pmDataOut.Octets = pmData.Octets
3764 }
3765 if pmData.Frames != errorCounterValue {
3766 pmDataOut.Frames = pmData.Frames + pmDataIn["frames"]
3767 } else {
3768 pmDataOut.Frames = pmData.Frames
3769 }
3770 if pmData.BroadcastFrames != errorCounterValue {
3771 pmDataOut.BroadcastFrames = pmData.BroadcastFrames + pmDataIn["broadcast_frames"]
3772 } else {
3773 pmDataOut.BroadcastFrames = pmData.BroadcastFrames
3774 }
3775 if pmData.MulticastFrames != errorCounterValue {
3776 pmDataOut.MulticastFrames = pmData.MulticastFrames + pmDataIn["multicast_frames"]
3777 } else {
3778 pmDataOut.MulticastFrames = pmData.MulticastFrames
3779 }
3780 if pmData.CrcErroredFrames != errorCounterValue {
3781 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames + pmDataIn["crc_errored_frames"]
3782 } else {
3783 pmDataOut.CrcErroredFrames = pmData.CrcErroredFrames
3784 }
3785 if pmData.UndersizeFrames != errorCounterValue {
3786 pmDataOut.UndersizeFrames = pmData.UndersizeFrames + pmDataIn["undersize_frames"]
3787 } else {
3788 pmDataOut.UndersizeFrames = pmData.UndersizeFrames
3789 }
3790 if pmData.OversizeFrames != errorCounterValue {
3791 pmDataOut.OversizeFrames = pmData.OversizeFrames + pmDataIn["oversize_frames"]
3792 } else {
3793 pmDataOut.OversizeFrames = pmData.OversizeFrames
3794 }
3795 if pmData.Frames_64Octets != errorCounterValue {
3796 pmDataOut.Frames_64Octets = pmData.Frames_64Octets + pmDataIn["64_octets"]
3797 } else {
3798 pmDataOut.Frames_64Octets = pmData.Frames_64Octets
3799 }
3800 if pmData.Frames_65To_127Octets != errorCounterValue {
3801 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets + pmDataIn["65_to_127_octets"]
3802 } else {
3803 pmDataOut.Frames_65To_127Octets = pmData.Frames_65To_127Octets
3804 }
3805 if pmData.Frames_128To_255Octets != errorCounterValue {
3806 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets + pmDataIn["128_to_255_octets"]
3807 } else {
3808 pmDataOut.Frames_128To_255Octets = pmData.Frames_128To_255Octets
3809 }
3810 if pmData.Frames_256To_511Octets != errorCounterValue {
3811 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets + pmDataIn["256_to_511_octets"]
3812 } else {
3813 pmDataOut.Frames_256To_511Octets = pmData.Frames_256To_511Octets
3814 }
3815 if pmData.Frames_512To_1023Octets != errorCounterValue {
3816 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets + pmDataIn["512_to_1023_octets"]
3817 } else {
3818 pmDataOut.Frames_512To_1023Octets = pmData.Frames_512To_1023Octets
3819 }
3820 if pmData.Frames_1024To_1518Octets != errorCounterValue {
3821 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets + pmDataIn["1024_to_1518_octets"]
3822 } else {
3823 pmDataOut.Frames_1024To_1518Octets = pmData.Frames_1024To_1518Octets
3824 }
3825 } else {
3826 pmDataOut.DropEvents = pmDataIn["drop_events"]
3827 pmDataOut.Octets = pmDataIn["octets"]
3828 pmDataOut.Frames = pmDataIn["frames"]
3829 pmDataOut.BroadcastFrames = pmDataIn["broadcast_frames"]
3830 pmDataOut.MulticastFrames = pmDataIn["multicast_frames"]
3831 pmDataOut.CrcErroredFrames = pmDataIn["crc_errored_frames"]
3832 pmDataOut.UndersizeFrames = pmDataIn["undersize_frames"]
3833 pmDataOut.OversizeFrames = pmDataIn["oversize_frames"]
3834 pmDataOut.Frames_64Octets = pmDataIn["64_octets"]
3835 pmDataOut.Frames_65To_127Octets = pmDataIn["65_to_127_octets"]
3836 pmDataOut.Frames_128To_255Octets = pmDataIn["128_to_255_octets"]
3837 pmDataOut.Frames_256To_511Octets = pmDataIn["256_to_511_octets"]
3838 pmDataOut.Frames_512To_1023Octets = pmDataIn["512_to_1023_octets"]
3839 pmDataOut.Frames_1024To_1518Octets = pmDataIn["1024_to_1518_octets"]
3840 }
3841 return pmDataOut
3842}
3843
Himani Chawlaee10b542021-09-20 16:46:40 +05303844func (mm *OnuMetricsManager) getControlBlockForExtendedPMDirection(ctx context.Context, upstream bool, entityID uint16, reset bool) []uint16 {
Himani Chawla43f95ff2021-06-03 00:24:12 +05303845 controlBlock := make([]uint16, 8)
3846 // Control Block First two bytes are for threshold data 1/2 id - does not matter here
3847 controlBlock[0] = 0
3848 // Next two bytes are for the parent class ID
3849 controlBlock[1] = (uint16)(me.PhysicalPathTerminationPointEthernetUniClassID)
3850 // Next two bytes are for the parent me instance id
3851 controlBlock[2] = entityID
3852 // Next two bytes are for accumulation disable
Himani Chawlaee10b542021-09-20 16:46:40 +05303853 if reset {
3854 controlBlock[3] = 1 << 15 //Set the 16th bit of AD to reset the counters.
3855 } else {
3856 controlBlock[3] = 0
3857 }
Himani Chawla43f95ff2021-06-03 00:24:12 +05303858 // Next two bytes are for tca disable
3859 controlBlock[4] = 0x4000 //tca global disable
3860 // Next two bytes are for control fields - bit 1(lsb) as 1 for continuous accumulation and bit 2(0 for upstream)
3861 if upstream {
3862 controlBlock[5] = 1 << 0
3863 } else {
3864 controlBlock[5] = (1 << 0) | (1 << 1)
3865 }
3866 // Next two bytes are for tci - does not matter here
3867 controlBlock[6] = 0
3868 // Next two bytes are for reserved bits - does not matter here
3869 controlBlock[7] = 0
3870 return controlBlock
3871}