blob: 447704b5d02ce069750cf02247ae30fc1cb477ac [file] [log] [blame]
Abhilash S.L765ad002019-04-24 16:40:57 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2019-2024 Open Networking Foundation (ONF) and the ONF Contributors
Abhilash S.L765ad002019-04-24 16:40:57 +05303
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 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Joey Armstrong3f0e2422023-07-05 18:25:41 -040017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package core
Abhilash S.L765ad002019-04-24 16:40:57 +053019
20import (
kesavand62126212021-01-12 04:56:06 -050021 "container/list"
Neha Sharma96b7bf22020-06-15 10:37:32 +000022 "context"
Abhilash S.L765ad002019-04-24 16:40:57 +053023 "fmt"
Shrey Baid26912972020-04-16 21:02:31 +053024 "sync"
25 "time"
26
Mahir Gunyel85f61c12021-10-06 11:53:45 -070027 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040028 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
29
30 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Thomas Lee S94109f12020-03-03 16:39:29 +053031 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053032 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo106c61a2021-08-11 18:05:46 -040033 "github.com/opencord/voltha-protos/v5/go/extension"
34 "github.com/opencord/voltha-protos/v5/go/openolt"
35 "github.com/opencord/voltha-protos/v5/go/voltha"
Abhilash S.L765ad002019-04-24 16:40:57 +053036)
37
Gamze Abakafcbd6e72020-12-17 13:25:16 +000038const (
Akash Kankanala041a2122024-10-16 15:49:22 +053039 // NNIStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000040 NNIStats = "NNIStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053041 // PONStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000042 PONStats = "PONStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053043 // ONUStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000044 ONUStats = "ONUStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053045 // GEMStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000046 GEMStats = "GEMStats"
47
Akash Kankanala041a2122024-10-16 15:49:22 +053048 // RxBytes constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000049 RxBytes = "RxBytes"
Akash Kankanala041a2122024-10-16 15:49:22 +053050 // RxPackets constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000051 RxPackets = "RxPackets"
Akash Kankanala041a2122024-10-16 15:49:22 +053052 // TxBytes constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000053 TxBytes = "TxBytes"
Akash Kankanala041a2122024-10-16 15:49:22 +053054 // TxPackets constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000055 TxPackets = "TxPackets"
Akash Kankanala041a2122024-10-16 15:49:22 +053056 // FecCodewords constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000057 FecCodewords = "FecCodewords"
Akash Kankanala041a2122024-10-16 15:49:22 +053058 // BipUnits constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000059 BipUnits = "BipUnits"
Akash Kankanala041a2122024-10-16 15:49:22 +053060 // BipErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000061 BipErrors = "BipErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053062 // RxPloamsNonIdle constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000063 RxPloamsNonIdle = "RxPloamsNonIdle"
Akash Kankanala041a2122024-10-16 15:49:22 +053064 // RxPloamsError constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000065 RxPloamsError = "RxPloamsError"
Akash Kankanala041a2122024-10-16 15:49:22 +053066 // RxOmci constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000067 RxOmci = "RxOmci"
Akash Kankanala041a2122024-10-16 15:49:22 +053068 // RxOmciPacketsCrcError constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000069 RxOmciPacketsCrcError = "RxOmciPacketsCrcError"
Akash Kankanala041a2122024-10-16 15:49:22 +053070 // PositiveDrift constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000071 PositiveDrift = "PositiveDrift"
Akash Kankanala041a2122024-10-16 15:49:22 +053072 // NegativeDrift constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000073 NegativeDrift = "NegativeDrift"
Akash Kankanala041a2122024-10-16 15:49:22 +053074 // DelimiterMissDetection constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000075 DelimiterMissDetection = "DelimiterMissDetection"
Akash Kankanala041a2122024-10-16 15:49:22 +053076 // FecCorrectedSymbols constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000077 FecCorrectedSymbols = "FecCorrectedSymbols"
Akash Kankanala041a2122024-10-16 15:49:22 +053078 // FecCodewordsCorrected constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000079 FecCodewordsCorrected = "FecCodewordsCorrected"
Akash Kankanala041a2122024-10-16 15:49:22 +053080 // fecCodewordsUncorrectable constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000081 fecCodewordsUncorrectable = "fec_codewords_uncorrectable"
Akash Kankanala041a2122024-10-16 15:49:22 +053082 // FecCorrectedUnits constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000083 FecCorrectedUnits = "FecCorrectedUnits"
Akash Kankanala041a2122024-10-16 15:49:22 +053084 // XGEMKeyErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000085 XGEMKeyErrors = "XGEMKeyErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053086 // XGEMLoss constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000087 XGEMLoss = "XGEMLOSS"
Akash Kankanala041a2122024-10-16 15:49:22 +053088 // BerReported constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000089 BerReported = "BerReported"
Akash Kankanala041a2122024-10-16 15:49:22 +053090 // LcdgErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000091 LcdgErrors = "LcdgErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053092 // RdiErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000093 RdiErrors = "RdiErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053094 // Timestamp constant
Himani Chawla2c8ae0f2021-05-18 23:27:00 +053095 Timestamp = "Timestamp"
Gamze Abakafcbd6e72020-12-17 13:25:16 +000096)
97
Naga Manjunath7615e552019-10-11 22:35:47 +053098var mutex = &sync.Mutex{}
99
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000100var onuStats = make(chan *openolt.OnuStatistics, 100)
101var gemStats = make(chan *openolt.GemPortStatistics, 100)
102
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400103// statRegInfo is used to register for notifications
104// on receiving port stats and flow stats indication
kesavand62126212021-01-12 04:56:06 -0500105type statRegInfo struct {
106 chn chan bool
107 portNo uint32
108 portType extension.GetOltPortCounters_PortType
109}
110
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111// PonPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530112type PonPort struct {
Abhilash S.L765ad002019-04-24 16:40:57 +0530113 ONUs map[uint32]interface{}
114 ONUsByID map[uint32]interface{}
115
Akash Kankanala041a2122024-10-16 15:49:22 +0530116 DeviceID string
117 Label string
118
akashreddyk302516f2025-11-17 15:18:44 +0530119 RxBytes uint64
120 RxPackets uint64
121 RxUcastPackets uint64
122 RxMcastPackets uint64
123 RxBcastPackets uint64
124 RxErrorPackets uint64
125 RxPacketsDropped uint64
126 TxBytes uint64
127 TxPackets uint64
128 TxUcastPackets uint64
129 TxMcastPackets uint64
130 TxBcastPackets uint64
131 TxErrorPackets uint64
132 TxDroppedTotal uint64
133 RxCrcErrors uint64
134 BipErrors uint64
Akash Kankanala041a2122024-10-16 15:49:22 +0530135 /*
136 This is a highly reduced version taken from the adtran pon_port.
137 TODO: Extend for use in the openolt adapter set.
138 */
139 /* MAX_ONUS_SUPPORTED = 256
140 DEFAULT_ENABLED = False
141 MAX_DEPLOYMENT_RANGE = 25000 # Meters (OLT-PB maximum)
142
143 _MCAST_ONU_ID = 253
144 _MCAST_ALLOC_BASE = 0x500
145
146 _SUPPORTED_ACTIVATION_METHODS = ['autodiscovery'] # , 'autoactivate']
147 _SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
148 */
149 PONID uint32
150 IntfID uint32
151 PortNum uint32
152 PortID uint32
Abhilash S.L765ad002019-04-24 16:40:57 +0530153}
154
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700155// NewPONPort returns a new instance of PonPort initialized with given PONID, DeviceID, IntfID and PortNum
Abhilash S.L765ad002019-04-24 16:40:57 +0530156func NewPONPort(PONID uint32, DeviceID string, IntfID uint32, PortNum uint32) *PonPort {
Abhilash S.L765ad002019-04-24 16:40:57 +0530157 var PON PonPort
158
159 PON.PONID = PONID
160 PON.DeviceID = DeviceID
161 PON.IntfID = IntfID
162 PON.PortNum = PortNum
163 PON.PortID = 0
Naga Manjunath7615e552019-10-11 22:35:47 +0530164 PON.Label = fmt.Sprintf("%s%d", "pon-", PONID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530165
166 PON.ONUs = make(map[uint32]interface{})
167 PON.ONUsByID = make(map[uint32]interface{})
168
169 /*
170 Statistics taken from nni_port
171 self.intf_id = 0 #handled by getter
172 self.port_no = 0 #handled by getter
173 self.port_id = 0 #handled by getter
174
175 Note: In the current implementation of the kpis coming from the BAL the stats are the
176 samne model for NNI and PON.
177
178 TODO: Integrate additional kpis for the PON and other southbound port objecgts.
179
180 */
181
182 PON.RxBytes = 0
183 PON.RxPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000184 PON.RxUcastPackets = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530185 PON.RxMcastPackets = 0
186 PON.RxBcastPackets = 0
187 PON.RxErrorPackets = 0
188 PON.TxBytes = 0
189 PON.TxPackets = 0
190 PON.TxUcastPackets = 0
191 PON.TxMcastPackets = 0
192 PON.TxBcastPackets = 0
193 PON.TxErrorPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000194 PON.RxCrcErrors = 0
195 PON.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530196
197 /* def __str__(self):
198 return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
199 self._admin_state,
200 self._oper_status,
201 self.olt)
202 */
203 return &PON
204}
205
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700206// NniPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530207type NniPort struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530208 Name string
Abhilash S.L765ad002019-04-24 16:40:57 +0530209
akashreddyk302516f2025-11-17 15:18:44 +0530210 RxBytes uint64
211 RxPackets uint64
212 RxUcastPackets uint64
213 RxMcastPackets uint64
214 RxBcastPackets uint64
215 RxErrorPackets uint64
216 RxPacketsDropped uint64
217 TxBytes uint64
218 TxPackets uint64
219 TxUcastPackets uint64
220 TxMcastPackets uint64
221 TxBcastPackets uint64
222 TxErrorPackets uint64
223 TxDroppedTotal uint64
224 RxCrcErrors uint64
225 BipErrors uint64
Akash Kankanala041a2122024-10-16 15:49:22 +0530226 /*
227 Northbound network port, often Ethernet-based
228
229 This is a highly reduced version taken from the adtran nni_port code set
230 TODO: add functions to allow for port specific values and operations
231 */
232 PortNum uint32
233 LogicalPort uint32
234 IntfID uint32
Abhilash S.L765ad002019-04-24 16:40:57 +0530235}
236
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700237// NewNniPort returns a new instance of NniPort initialized with the given PortNum and IntfID
Abhilash S.L765ad002019-04-24 16:40:57 +0530238func NewNniPort(PortNum uint32, IntfID uint32) *NniPort {
Abhilash S.L765ad002019-04-24 16:40:57 +0530239 var NNI NniPort
240
241 NNI.PortNum = PortNum
Naga Manjunath7615e552019-10-11 22:35:47 +0530242 NNI.Name = fmt.Sprintf("%s%d", "nni-", PortNum)
Abhilash S.L765ad002019-04-24 16:40:57 +0530243 NNI.IntfID = IntfID
244
245 NNI.RxBytes = 0
246 NNI.RxPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000247 NNI.RxUcastPackets = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530248 NNI.RxMcastPackets = 0
249 NNI.RxBcastPackets = 0
250 NNI.RxErrorPackets = 0
251 NNI.TxBytes = 0
252 NNI.TxPackets = 0
253 NNI.TxUcastPackets = 0
254 NNI.TxMcastPackets = 0
255 NNI.TxBcastPackets = 0
256 NNI.TxErrorPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000257 NNI.RxCrcErrors = 0
258 NNI.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530259
260 return &NNI
261}
262
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400263// StatType defines portStatsType and flowStatsType types
kesavand62126212021-01-12 04:56:06 -0500264type StatType int
265
266const (
267 portStatsType StatType = iota
268 flowStatsType
269)
270
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700271// OpenOltStatisticsMgr structure
Abhilash S.L765ad002019-04-24 16:40:57 +0530272type OpenOltStatisticsMgr struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530273 Device *DeviceHandler
274 NorthBoundPort map[uint32]*NniPort
275 SouthBoundPort map[uint32]*PonPort
276 statIndListners map[StatType]*list.List
Abhilash S.L765ad002019-04-24 16:40:57 +0530277 // TODO PMMetrics Metrics
Akash Kankanala041a2122024-10-16 15:49:22 +0530278 // statIndListners is the list of requests to be notified when port and flow stats indication is received
kesavand62126212021-01-12 04:56:06 -0500279 statIndListnerMu sync.Mutex
Abhilash S.L765ad002019-04-24 16:40:57 +0530280}
281
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700282// NewOpenOltStatsMgr returns a new instance of the OpenOltStatisticsMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000283func NewOpenOltStatsMgr(ctx context.Context, Dev *DeviceHandler) *OpenOltStatisticsMgr {
Abhilash S.L765ad002019-04-24 16:40:57 +0530284 var StatMgr OpenOltStatisticsMgr
285
286 StatMgr.Device = Dev
287 // TODO call metric PMMetric =
288 // Northbound and Southbound ports
289 // added to initialize the pm_metrics
290 var Ports interface{}
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530291 NumNniPorts := Dev.resourceMgr[0].DevInfo.GetNniPorts()
292 Ports, _ = InitPorts(ctx, "nni", Dev.device.Id, NumNniPorts)
Naga Manjunath7615e552019-10-11 22:35:47 +0530293 StatMgr.NorthBoundPort, _ = Ports.(map[uint32]*NniPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700294 NumPonPorts := Dev.resourceMgr[0].DevInfo.GetPonPorts()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000295 Ports, _ = InitPorts(ctx, "pon", Dev.device.Id, NumPonPorts)
Naga Manjunath7615e552019-10-11 22:35:47 +0530296 StatMgr.SouthBoundPort, _ = Ports.(map[uint32]*PonPort)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000297 if StatMgr.Device.openOLT.enableONUStats {
298 go StatMgr.publishOnuStats()
299 }
300 if StatMgr.Device.openOLT.enableGemStats {
301 go StatMgr.publishGemStats()
302 }
kesavand62126212021-01-12 04:56:06 -0500303 StatMgr.statIndListners = make(map[StatType]*list.List)
304 StatMgr.statIndListners[portStatsType] = list.New()
305 StatMgr.statIndListners[flowStatsType] = list.New()
Abhilash S.L765ad002019-04-24 16:40:57 +0530306 return &StatMgr
307}
308
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700309// InitPorts collects the port objects: nni and pon that are updated with the current data from the OLT
Neha Sharma96b7bf22020-06-15 10:37:32 +0000310func InitPorts(ctx context.Context, Intftype string, DeviceID string, numOfPorts uint32) (interface{}, error) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530311 /*
312 This method collects the port objects: nni and pon that are updated with the
313 current data from the OLT
314
315 Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
316 and NOT the port number. When the port object is instantiated it will contain the intf_id and
317 port_no values
318
319 :param type:
320 :return:
321 */
322 var i uint32
mgouda86543582025-10-29 20:58:16 +0530323 switch Intftype {
324 case "nni":
Naga Manjunath7615e552019-10-11 22:35:47 +0530325 NniPorts := make(map[uint32]*NniPort)
326 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327 Port := BuildPortObject(ctx, i, "nni", DeviceID).(*NniPort)
Naga Manjunath7615e552019-10-11 22:35:47 +0530328 NniPorts[Port.IntfID] = Port
Abhilash S.L765ad002019-04-24 16:40:57 +0530329 }
330 return NniPorts, nil
mgouda86543582025-10-29 20:58:16 +0530331 case "pon":
Naga Manjunath7615e552019-10-11 22:35:47 +0530332 PONPorts := make(map[uint32]*PonPort)
333 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000334 PONPort := BuildPortObject(ctx, i, "pon", DeviceID).(*PonPort)
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700335 PONPorts[plt.PortNoToIntfID(PONPort.IntfID, voltha.Port_PON_OLT)] = PONPort
Abhilash S.L765ad002019-04-24 16:40:57 +0530336 }
337 return PONPorts, nil
mgouda86543582025-10-29 20:58:16 +0530338 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000339 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"interface-type": Intftype})
Thomas Lee S94109f12020-03-03 16:39:29 +0530340 return nil, olterrors.NewErrInvalidValue(log.Fields{"interface-type": Intftype}, nil)
Abhilash S.L765ad002019-04-24 16:40:57 +0530341 }
342}
343
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700344// BuildPortObject allows for updating north and southbound ports, newly discovered ports, and devices
Neha Sharma96b7bf22020-06-15 10:37:32 +0000345func BuildPortObject(ctx context.Context, PortNum uint32, IntfType string, DeviceID string) interface{} {
Abhilash S.L765ad002019-04-24 16:40:57 +0530346 /*
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700347 Separate method to allow for updating north and southbound ports
Abhilash S.L765ad002019-04-24 16:40:57 +0530348 newly discovered ports and devices
349
350 :param port_num:
351 :param type:
352 :return:
353 */
354
Akash Kankanala041a2122024-10-16 15:49:22 +0530355 // This builds a port object which is added to the
356 // appropriate northbound or southbound values
mgouda86543582025-10-29 20:58:16 +0530357 switch IntfType {
358 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700359 IntfID := plt.IntfIDToPortNo(PortNum, voltha.Port_ETHERNET_NNI)
360 nniID := plt.PortNoToIntfID(IntfID, voltha.Port_ETHERNET_NNI)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "interface-type-nni",
Shrey Baid26912972020-04-16 21:02:31 +0530362 log.Fields{
363 "nni-id": nniID,
364 "intf-type": IntfType})
Naga Manjunath7615e552019-10-11 22:35:47 +0530365 return NewNniPort(PortNum, nniID)
mgouda86543582025-10-29 20:58:16 +0530366 case "pon":
Abhilash S.L765ad002019-04-24 16:40:57 +0530367 // PON ports require a different configuration
368 // intf_id and pon_id are currently equal.
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700369 IntfID := plt.IntfIDToPortNo(PortNum, voltha.Port_PON_OLT)
370 PONID := plt.PortNoToIntfID(IntfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Debugw(ctx, "interface-type-pon",
Shrey Baid26912972020-04-16 21:02:31 +0530372 log.Fields{
373 "pon-id": PONID,
374 "intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530375 return NewPONPort(PONID, DeviceID, IntfID, PortNum)
mgouda86543582025-10-29 20:58:16 +0530376 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000377 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530378 return nil
379 }
380}
381
Naga Manjunath7615e552019-10-11 22:35:47 +0530382// collectNNIMetrics will collect the nni port metrics
383func (StatMgr *OpenOltStatisticsMgr) collectNNIMetrics(nniID uint32) map[string]float32 {
Naga Manjunath7615e552019-10-11 22:35:47 +0530384 nnival := make(map[string]float32)
385 mutex.Lock()
386 cm := StatMgr.Device.portStats.NorthBoundPort[nniID]
387 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000388 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530389
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000390 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400391 for metric := range metricNames {
392 if metricNames[metric].Enabled {
393 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530394 }
395 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000396
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530397 if cm != nil {
398 for _, mName := range metrics {
399 switch mName {
400 case "rx_bytes":
401 nnival["RxBytes"] = float32(cm.RxBytes)
402 case "rx_packets":
403 nnival["RxPackets"] = float32(cm.RxPackets)
404 case "rx_ucast_packets":
405 nnival["RxUcastPackets"] = float32(cm.RxUcastPackets)
406 case "rx_mcast_packets":
407 nnival["RxMcastPackets"] = float32(cm.RxMcastPackets)
408 case "rx_bcast_packets":
409 nnival["RxBcastPackets"] = float32(cm.RxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530410 case "rx_error_packets":
411 nnival["RxErrorPackets"] = float32(cm.RxErrorPackets)
412 case "rx_crc_errors":
413 nnival["RxCrcErrors"] = float32(cm.RxCrcErrors)
414 case "rx_packets_dropped":
415 nnival["RxPacketsDropped"] = float32(cm.RxPacketsDropped)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530416 case "tx_bytes":
417 nnival["TxBytes"] = float32(cm.TxBytes)
418 case "tx_packets":
419 nnival["TxPackets"] = float32(cm.TxPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530420 case "tx_ucast_packets":
421 nnival["TxUcastPackets"] = float32(cm.TxUcastPackets)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530422 case "tx_mcast_packets":
423 nnival["TxMcastPackets"] = float32(cm.TxMcastPackets)
424 case "tx_bcast_packets":
425 nnival["TxBcastPackets"] = float32(cm.TxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530426 case "tx_dropped_total":
427 nnival["TxDroppedTotal"] = float32(cm.TxDroppedTotal)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530428 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000429 }
430 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530431 return nnival
432}
433
434// collectPONMetrics will collect the pon port metrics
435func (StatMgr *OpenOltStatisticsMgr) collectPONMetrics(pID uint32) map[string]float32 {
Naga Manjunath7615e552019-10-11 22:35:47 +0530436 ponval := make(map[string]float32)
437 mutex.Lock()
438 cm := StatMgr.Device.portStats.SouthBoundPort[pID]
439 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000440 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530441
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000442 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400443 for metric := range metricNames {
444 if metricNames[metric].Enabled {
445 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530446 }
447 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000448
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530449 if cm != nil {
450 for _, mName := range metrics {
451 switch mName {
452 case "rx_bytes":
453 ponval["RxBytes"] = float32(cm.RxBytes)
454 case "rx_packets":
455 ponval["RxPackets"] = float32(cm.RxPackets)
456 case "rx_ucast_packets":
457 ponval["RxUcastPackets"] = float32(cm.RxUcastPackets)
458 case "rx_mcast_packets":
459 ponval["RxMcastPackets"] = float32(cm.RxMcastPackets)
460 case "rx_bcast_packets":
461 ponval["RxBcastPackets"] = float32(cm.RxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530462 case "rx_error_packets":
463 ponval["RxErrorPackets"] = float32(cm.RxErrorPackets)
464 case "rx_packets_dropped":
465 ponval["RxPacketsDropped"] = float32(cm.RxPacketsDropped)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530466 case "tx_bytes":
467 ponval["TxBytes"] = float32(cm.TxBytes)
468 case "tx_packets":
469 ponval["TxPackets"] = float32(cm.TxPackets)
470 case "tx_mcast_packets":
471 ponval["TxMcastPackets"] = float32(cm.TxMcastPackets)
472 case "tx_bcast_packets":
473 ponval["TxBcastPackets"] = float32(cm.TxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530474 case "tx_error_packets":
475 ponval["TxErrorPackets"] = float32(cm.TxErrorPackets)
476 case "tx_dropped_total":
477 ponval["TxDroppedTotal"] = float32(cm.TxDroppedTotal)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530478 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000479 }
480 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530481 return ponval
482}
483
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000484// converGemStats will convert gem stats response to kpi context
485func (StatMgr *OpenOltStatisticsMgr) convertGemStats(gemStats *openolt.GemPortStatistics) map[string]float32 {
486 gemStatsVal := make(map[string]float32)
487 gemStatsVal[IntfID] = float32(gemStats.IntfId)
488 gemStatsVal[GemID] = float32(gemStats.GemportId)
489 gemStatsVal[RxPackets] = float32(gemStats.RxPackets)
490 gemStatsVal[RxBytes] = float32(gemStats.RxBytes)
491 gemStatsVal[TxPackets] = float32(gemStats.TxPackets)
492 gemStatsVal[TxBytes] = float32(gemStats.TxBytes)
493 return gemStatsVal
494}
495
496// convertONUStats will convert onu stats response to kpi context
497func (StatMgr *OpenOltStatisticsMgr) convertONUStats(onuStats *openolt.OnuStatistics) map[string]float32 {
498 onuStatsVal := make(map[string]float32)
499 onuStatsVal[IntfID] = float32(onuStats.IntfId)
500 onuStatsVal[OnuID] = float32(onuStats.OnuId)
501 onuStatsVal[PositiveDrift] = float32(onuStats.PositiveDrift)
502 onuStatsVal[NegativeDrift] = float32(onuStats.NegativeDrift)
503 onuStatsVal[DelimiterMissDetection] = float32(onuStats.DelimiterMissDetection)
504 onuStatsVal[BipErrors] = float32(onuStats.BipErrors)
505 onuStatsVal[BipUnits] = float32(onuStats.BipUnits)
506 onuStatsVal[FecCorrectedSymbols] = float32(onuStats.FecCorrectedSymbols)
507 onuStatsVal[FecCodewordsCorrected] = float32(onuStats.FecCodewordsCorrected)
508 onuStatsVal[fecCodewordsUncorrectable] = float32(onuStats.FecCodewordsUncorrectable)
509 onuStatsVal[FecCodewords] = float32(onuStats.FecCodewords)
510 onuStatsVal[FecCorrectedUnits] = float32(onuStats.FecCorrectedUnits)
511 onuStatsVal[XGEMKeyErrors] = float32(onuStats.XgemKeyErrors)
512 onuStatsVal[XGEMLoss] = float32(onuStats.XgemLoss)
513 onuStatsVal[RxPloamsError] = float32(onuStats.RxPloamsError)
514 onuStatsVal[RxPloamsNonIdle] = float32(onuStats.RxPloamsNonIdle)
515 onuStatsVal[RxOmci] = float32(onuStats.RxOmci)
516 onuStatsVal[RxOmciPacketsCrcError] = float32(onuStats.RxOmciPacketsCrcError)
517 onuStatsVal[RxBytes] = float32(onuStats.RxBytes)
518 onuStatsVal[RxPackets] = float32(onuStats.RxPackets)
519 onuStatsVal[TxBytes] = float32(onuStats.TxBytes)
520 onuStatsVal[TxPackets] = float32(onuStats.TxPackets)
521 onuStatsVal[BerReported] = float32(onuStats.BerReported)
522 onuStatsVal[LcdgErrors] = float32(onuStats.LcdgErrors)
523 onuStatsVal[RdiErrors] = float32(onuStats.RdiErrors)
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530524 onuStatsVal[Timestamp] = float32(onuStats.Timestamp)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000525 return onuStatsVal
526}
527
528// collectOnuStats will collect the onu metrics
529func (StatMgr *OpenOltStatisticsMgr) collectOnuStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
530 onu := &openolt.Onu{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID}
531 logger.Debugw(ctx, "pulling-onu-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID})
532 if stats, err := StatMgr.Device.Client.GetOnuStatistics(context.Background(), onu); err == nil {
533 onuStats <- stats
534 } else {
535 logger.Errorw(ctx, "error-while-getting-onu-stats-for-onu", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "err": err})
536 }
537}
538
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530539// collectOnDemandOnuStats will collect the onui-pon metrics
540func (StatMgr *OpenOltStatisticsMgr) collectOnDemandOnuStats(ctx context.Context, intfID uint32, onuID uint32) map[string]float32 {
541 onu := &openolt.Onu{IntfId: intfID, OnuId: onuID}
542 var stats *openolt.OnuStatistics
543 var err error
544 logger.Debugw(ctx, "pulling-onu-stats-on-demand", log.Fields{"IntfID": intfID, "OnuID": onuID})
545 if stats, err = StatMgr.Device.Client.GetOnuStatistics(context.Background(), onu); err == nil {
546 statValue := StatMgr.convertONUStats(stats)
547 return statValue
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530548 }
549 logger.Errorw(ctx, "error-while-getting-onu-stats-for-onu", log.Fields{"IntfID": intfID, "OnuID": onuID, "err": err})
550 return nil
551}
552
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000553// collectOnuAndGemStats will collect both onu and gem metrics
554func (StatMgr *OpenOltStatisticsMgr) collectOnuAndGemStats(ctx context.Context, onuGemInfo []rsrcMgr.OnuGemInfo) {
555 if !StatMgr.Device.openOLT.enableONUStats && !StatMgr.Device.openOLT.enableGemStats {
556 return
557 }
558
559 for _, onuInfo := range onuGemInfo {
560 if StatMgr.Device.openOLT.enableONUStats {
561 go StatMgr.collectOnuStats(ctx, onuInfo)
562 }
563 if StatMgr.Device.openOLT.enableGemStats {
564 go StatMgr.collectGemStats(ctx, onuInfo)
565 }
566 }
567}
568
569// collectGemStats will collect gem metrics
570func (StatMgr *OpenOltStatisticsMgr) collectGemStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
571 for _, gem := range onuGemInfo.GemPorts {
572 logger.Debugw(ctx, "pulling-gem-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem})
573 onuPacket := &openolt.OnuPacket{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID, GemportId: gem}
574 if stats, err := StatMgr.Device.Client.GetGemPortStatistics(context.Background(), onuPacket); err == nil {
575 gemStats <- stats
576 } else {
577 logger.Errorw(ctx, "error-while-getting-gem-stats-for-onu",
578 log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem, "err": err})
579 }
580 }
581}
582
583// publishGemStats will publish the gem metrics
584func (StatMgr *OpenOltStatisticsMgr) publishGemStats() {
585 for {
586 statValue := StatMgr.convertGemStats(<-gemStats)
587 StatMgr.publishMetrics(context.Background(), GEMStats, statValue, &voltha.Port{Label: "GEM"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
588 }
589}
590
591// publishOnuStats will publish the onu metrics
592func (StatMgr *OpenOltStatisticsMgr) publishOnuStats() {
593 for {
594 statValue := StatMgr.convertONUStats(<-onuStats)
595 StatMgr.publishMetrics(context.Background(), ONUStats, statValue, &voltha.Port{Label: "ONU"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
596 }
597}
598
599// publishMetrics will publish the pon port metrics
kesavand62126212021-01-12 04:56:06 -0500600func (StatMgr *OpenOltStatisticsMgr) publishMetrics(ctx context.Context, statType string, val map[string]float32,
Girish Gowdra34815db2020-05-11 17:18:04 -0700601 port *voltha.Port, devID string, devType string) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Debugw(ctx, "publish-metrics",
Shrey Baid26912972020-04-16 21:02:31 +0530603 log.Fields{
604 "port": port.Label,
605 "metrics": val})
Naga Manjunath7615e552019-10-11 22:35:47 +0530606
607 var metricInfo voltha.MetricInformation
608 var ke voltha.KpiEvent2
Esin Karamanccb714b2019-11-29 15:02:06 +0000609 var volthaEventSubCatgry voltha.EventSubCategory_Types
Girish Gowdra34815db2020-05-11 17:18:04 -0700610 metricsContext := make(map[string]string)
611 metricsContext["oltid"] = devID
612 metricsContext["devicetype"] = devType
613 metricsContext["portlabel"] = port.Label
Naga Manjunath7615e552019-10-11 22:35:47 +0530614
mgouda86543582025-10-29 20:58:16 +0530615 switch statType {
616 case NNIStats:
Naga Manjunath7615e552019-10-11 22:35:47 +0530617 volthaEventSubCatgry = voltha.EventSubCategory_NNI
mgouda86543582025-10-29 20:58:16 +0530618 case PONStats:
Naga Manjunath7615e552019-10-11 22:35:47 +0530619 volthaEventSubCatgry = voltha.EventSubCategory_PON
mgouda86543582025-10-29 20:58:16 +0530620 case GEMStats, ONUStats:
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000621 volthaEventSubCatgry = voltha.EventSubCategory_ONT
Naga Manjunath7615e552019-10-11 22:35:47 +0530622 }
623
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700624 raisedTs := time.Now().Unix()
Naga Manjunath7615e552019-10-11 22:35:47 +0530625 mmd := voltha.MetricMetaData{
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000626 Title: statType,
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700627 Ts: float64(raisedTs),
Girish Gowdra34815db2020-05-11 17:18:04 -0700628 Context: metricsContext,
Naga Manjunath7615e552019-10-11 22:35:47 +0530629 DeviceId: devID,
630 }
631
632 metricInfo.Metadata = &mmd
633 metricInfo.Metrics = val
634
635 ke.SliceData = []*voltha.MetricInformation{&metricInfo}
636 ke.Type = voltha.KpiEventType_slice
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700637 ke.Ts = float64(raisedTs)
Naga Manjunath7615e552019-10-11 22:35:47 +0530638
Himani Chawla473496d2021-12-01 00:10:30 +0530639 if err := StatMgr.Device.EventProxy.SendKpiEvent(ctx, "STATS_PUBLISH_EVENT", &ke, voltha.EventCategory_EQUIPMENT, volthaEventSubCatgry, raisedTs); err != nil {
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000640 logger.Errorw(ctx, "failed-to-send-stats", log.Fields{"err": err})
Naga Manjunath7615e552019-10-11 22:35:47 +0530641 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530642}
643
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700644// PortStatisticsIndication handles the port statistics indication
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530645func (StatMgr *OpenOltStatisticsMgr) PortStatisticsIndication(ctx context.Context, PortStats *common.PortStatistics, NumPonPorts uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 StatMgr.PortsStatisticsKpis(ctx, PortStats, NumPonPorts)
647 logger.Debugw(ctx, "received-port-stats-indication", log.Fields{"port-stats": PortStats})
Akash Kankanala041a2122024-10-16 15:49:22 +0530648 // Indicate that PortStatisticsIndication is handled
649 // PortStats.IntfId is actually the port number
kesavand62126212021-01-12 04:56:06 -0500650 StatMgr.processStatIndication(ctx, portStatsType, PortStats.IntfId)
Abhilash S.L765ad002019-04-24 16:40:57 +0530651 // TODO send stats to core topic to the voltha kafka or a different kafka ?
652}
653
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700654// FlowStatisticsIndication to be implemented
Neha Sharma96b7bf22020-06-15 10:37:32 +0000655func FlowStatisticsIndication(ctx context.Context, self, FlowStats *openolt.FlowStatistics) {
656 logger.Debugw(ctx, "flow-stats-collected", log.Fields{"flow-stats": FlowStats})
Akash Kankanala041a2122024-10-16 15:49:22 +0530657 // TODO send to kafka ?
Abhilash S.L765ad002019-04-24 16:40:57 +0530658}
659
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700660// PortsStatisticsKpis map the port stats values into a dictionary, creates the kpiEvent and then publish to Kafka
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530661func (StatMgr *OpenOltStatisticsMgr) PortsStatisticsKpis(ctx context.Context, PortStats *common.PortStatistics, NumPonPorts uint32) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530662 /*map the port stats values into a dictionary
663 Create a kpoEvent and publish to Kafka
664
665 :param port_stats:
666 :return:
667 */
Akash Kankanala041a2122024-10-16 15:49:22 +0530668 // var err error
Abhilash S.L765ad002019-04-24 16:40:57 +0530669 IntfID := PortStats.IntfId
670
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700671 if (plt.IntfIDToPortNo(1, voltha.Port_ETHERNET_NNI) < IntfID) &&
672 (IntfID < plt.IntfIDToPortNo(4, voltha.Port_ETHERNET_NNI)) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530673 /*
674 for this release we are only interested in the first NNI for
675 Northbound.
676 we are not using the other 3
677 */
678 return
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700679 } else if plt.IntfIDToPortNo(0, voltha.Port_ETHERNET_NNI) == IntfID {
Naga Manjunath7615e552019-10-11 22:35:47 +0530680 var portNNIStat NniPort
681 portNNIStat.IntfID = IntfID
682 portNNIStat.PortNum = uint32(0)
683 portNNIStat.RxBytes = PortStats.RxBytes
684 portNNIStat.RxPackets = PortStats.RxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000685 portNNIStat.RxUcastPackets = PortStats.RxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530686 portNNIStat.RxMcastPackets = PortStats.RxMcastPackets
687 portNNIStat.RxBcastPackets = PortStats.RxBcastPackets
akashreddyk302516f2025-11-17 15:18:44 +0530688 portNNIStat.RxCrcErrors = PortStats.RxCrcErrors
689 portNNIStat.RxErrorPackets = PortStats.RxErrorPackets
690 portNNIStat.RxPacketsDropped = PortStats.RxPacketsDropped
Naga Manjunath7615e552019-10-11 22:35:47 +0530691 portNNIStat.TxBytes = PortStats.TxBytes
692 portNNIStat.TxPackets = PortStats.TxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000693 portNNIStat.TxUcastPackets = PortStats.TxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530694 portNNIStat.TxMcastPackets = PortStats.TxMcastPackets
695 portNNIStat.TxBcastPackets = PortStats.TxBcastPackets
akashreddyk302516f2025-11-17 15:18:44 +0530696 portNNIStat.TxErrorPackets = PortStats.TxErrorPackets
697 portNNIStat.TxDroppedTotal = PortStats.TxDroppedTotal
Naga Manjunath7615e552019-10-11 22:35:47 +0530698 mutex.Lock()
699 StatMgr.NorthBoundPort[0] = &portNNIStat
700 mutex.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 logger.Debugw(ctx, "received-nni-stats", log.Fields{"nni-stats": StatMgr.NorthBoundPort})
Naga Manjunath7615e552019-10-11 22:35:47 +0530702 }
703 for i := uint32(0); i < NumPonPorts; i++ {
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700704 if plt.IntfIDToPortNo(i, voltha.Port_PON_OLT) == IntfID {
Naga Manjunath7615e552019-10-11 22:35:47 +0530705 var portPonStat PonPort
706 portPonStat.IntfID = IntfID
707 portPonStat.PortNum = i
708 portPonStat.PONID = i
709 portPonStat.RxBytes = PortStats.RxBytes
710 portPonStat.RxPackets = PortStats.RxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000711 portPonStat.RxUcastPackets = PortStats.RxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530712 portPonStat.RxMcastPackets = PortStats.RxMcastPackets
713 portPonStat.RxBcastPackets = PortStats.RxBcastPackets
akashreddyk302516f2025-11-17 15:18:44 +0530714 portPonStat.RxErrorPackets = PortStats.RxErrorPackets
715 portPonStat.RxPacketsDropped = PortStats.RxPacketsDropped
Naga Manjunath7615e552019-10-11 22:35:47 +0530716 portPonStat.TxBytes = PortStats.TxBytes
717 portPonStat.TxPackets = PortStats.TxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000718 portPonStat.TxUcastPackets = PortStats.TxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530719 portPonStat.TxMcastPackets = PortStats.TxMcastPackets
720 portPonStat.TxBcastPackets = PortStats.TxBcastPackets
akashreddyk302516f2025-11-17 15:18:44 +0530721 portPonStat.TxErrorPackets = PortStats.TxErrorPackets
722 portPonStat.TxDroppedTotal = PortStats.TxDroppedTotal
Naga Manjunath7615e552019-10-11 22:35:47 +0530723 mutex.Lock()
724 StatMgr.SouthBoundPort[i] = &portPonStat
725 mutex.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000726 logger.Debugw(ctx, "received-pon-stats-for-port", log.Fields{"port-pon-stats": portPonStat})
Naga Manjunath7615e552019-10-11 22:35:47 +0530727 }
728 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700729 /*
730 Based upon the intf_id map to an nni port or a pon port
731 the intf_id is the key to the north or south bound collections
732
733 Based upon the intf_id the port object (nni_port or pon_port) will
734 have its data attr. updated by the current dataset collected.
735
736 For prefixing the rule is currently to use the port number and not the intf_id
737 */
Akash Kankanala041a2122024-10-16 15:49:22 +0530738 // FIXME : Just use first NNI for now
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700739 /* TODO should the data be marshaled before sending it ?
740 if IntfID == IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) {
741 //NNI port (just the first one)
742 err = UpdatePortObjectKpiData(StatMgr.NorthBoundPorts[PortStats.IntfID], PMData)
743 } else {
744 //PON ports
745 err = UpdatePortObjectKpiData(SouthboundPorts[PortStats.IntfID], PMData)
746 }
747 if (err != nil) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000748 logger.Error(ctx, "Error publishing statistics data")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700749 }
750 */
Abhilash S.L765ad002019-04-24 16:40:57 +0530751}
kesavand62126212021-01-12 04:56:06 -0500752
753func (StatMgr *OpenOltStatisticsMgr) updateGetOltPortCountersResponse(ctx context.Context, singleValResp *extension.SingleGetValueResponse, stats map[string]float32) {
kesavand62126212021-01-12 04:56:06 -0500754 metrics := singleValResp.GetResponse().GetPortCoutners()
755 metrics.TxBytes = uint64(stats["TxBytes"])
756 metrics.RxBytes = uint64(stats["RxBytes"])
757 metrics.TxPackets = uint64(stats["TxPackets"])
758 metrics.RxPackets = uint64(stats["RxPackets"])
759 metrics.TxErrorPackets = uint64(stats["TxErrorPackets"])
760 metrics.RxErrorPackets = uint64(stats["RxErrorPackets"])
761 metrics.TxBcastPackets = uint64(stats["TxBcastPackets"])
762 metrics.RxBcastPackets = uint64(stats["RxBcastPackets"])
763 metrics.TxUcastPackets = uint64(stats["TxUcastPackets"])
764 metrics.RxUcastPackets = uint64(stats["RxUcastPackets"])
765 metrics.TxMcastPackets = uint64(stats["TxMcastPackets"])
766 metrics.RxMcastPackets = uint64(stats["RxMcastPackets"])
767
768 singleValResp.Response.Status = extension.GetValueResponse_OK
769 logger.Debugw(ctx, "updateGetOltPortCountersResponse", log.Fields{"resp": singleValResp})
770}
771
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400772// RegisterForStatIndication registers ch as a channel on which indication is sent when statistics of type t is received
kesavand62126212021-01-12 04:56:06 -0500773func (StatMgr *OpenOltStatisticsMgr) RegisterForStatIndication(ctx context.Context, t StatType, ch chan bool, portNo uint32, portType extension.GetOltPortCounters_PortType) {
774 statInd := statRegInfo{
775 chn: ch,
776 portNo: portNo,
777 portType: portType,
778 }
779
780 logger.Debugf(ctx, "RegisterForStatIndication stat type %v portno %v porttype %v chan %v", t, portNo, portType, ch)
781 StatMgr.statIndListnerMu.Lock()
782 StatMgr.statIndListners[t].PushBack(statInd)
783 StatMgr.statIndListnerMu.Unlock()
kesavand62126212021-01-12 04:56:06 -0500784}
785
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400786// DeRegisterFromStatIndication removes the previously registered channel ch for type t of statistics
kesavand62126212021-01-12 04:56:06 -0500787func (StatMgr *OpenOltStatisticsMgr) DeRegisterFromStatIndication(ctx context.Context, t StatType, ch chan bool) {
788 StatMgr.statIndListnerMu.Lock()
789 defer StatMgr.statIndListnerMu.Unlock()
790
791 for e := StatMgr.statIndListners[t].Front(); e != nil; e = e.Next() {
792 statInd := e.Value.(statRegInfo)
793 if statInd.chn == ch {
794 StatMgr.statIndListners[t].Remove(e)
795 return
796 }
797 }
798}
799
800func (StatMgr *OpenOltStatisticsMgr) processStatIndication(ctx context.Context, t StatType, portNo uint32) {
801 var deRegList []*list.Element
802 var statInd statRegInfo
803
804 StatMgr.statIndListnerMu.Lock()
805 defer StatMgr.statIndListnerMu.Unlock()
806
807 if StatMgr.statIndListners[t] == nil || StatMgr.statIndListners[t].Len() == 0 {
808 logger.Debugf(ctx, "processStatIndication %v list is empty ", t)
809 return
810 }
811
812 for e := StatMgr.statIndListners[t].Front(); e != nil; e = e.Next() {
813 statInd = e.Value.(statRegInfo)
814 if statInd.portNo != portNo {
815 fmt.Printf("Skipping %v\n", e.Value)
816 continue
817 }
818 // message sent
819 statInd.chn <- true
820 deRegList = append(deRegList, e)
kesavand62126212021-01-12 04:56:06 -0500821 }
822 for _, e := range deRegList {
823 StatMgr.statIndListners[t].Remove(e)
824 }
kesavand62126212021-01-12 04:56:06 -0500825}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530826
827func (StatMgr *OpenOltStatisticsMgr) updateGetOnuPonCountersResponse(ctx context.Context, singleValResp *extension.SingleGetValueResponse, stats map[string]float32) {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530828 metrics := singleValResp.GetResponse().GetOnuPonCounters()
829 metrics.IsIntfId = &extension.GetOnuCountersResponse_IntfId{
830 IntfId: uint32(stats[IntfID]),
831 }
832 metrics.IsOnuId = &extension.GetOnuCountersResponse_OnuId{
833 OnuId: uint32(stats[OnuID]),
834 }
835 metrics.IsPositiveDrift = &extension.GetOnuCountersResponse_PositiveDrift{
836 PositiveDrift: uint64(stats[PositiveDrift]),
837 }
838 metrics.IsNegativeDrift = &extension.GetOnuCountersResponse_NegativeDrift{
839 NegativeDrift: uint64(stats[NegativeDrift]),
840 }
841 metrics.IsDelimiterMissDetection = &extension.GetOnuCountersResponse_DelimiterMissDetection{
842 DelimiterMissDetection: uint64(stats[DelimiterMissDetection]),
843 }
844 metrics.IsBipErrors = &extension.GetOnuCountersResponse_BipErrors{
845 BipErrors: uint64(stats[BipErrors]),
846 }
847 metrics.IsBipUnits = &extension.GetOnuCountersResponse_BipUnits{
848 BipUnits: uint64(stats[BipUnits]),
849 }
850 metrics.IsFecCorrectedSymbols = &extension.GetOnuCountersResponse_FecCorrectedSymbols{
851 FecCorrectedSymbols: uint64(stats[FecCorrectedSymbols]),
852 }
853 metrics.IsFecCodewordsCorrected = &extension.GetOnuCountersResponse_FecCodewordsCorrected{
854 FecCodewordsCorrected: uint64(stats[FecCodewordsCorrected]),
855 }
856 metrics.IsFecCodewordsUncorrectable = &extension.GetOnuCountersResponse_FecCodewordsUncorrectable{
857 FecCodewordsUncorrectable: uint64(stats[fecCodewordsUncorrectable]),
858 }
859 metrics.IsFecCodewords = &extension.GetOnuCountersResponse_FecCodewords{
860 FecCodewords: uint64(stats[FecCodewords]),
861 }
862 metrics.IsFecCorrectedUnits = &extension.GetOnuCountersResponse_FecCorrectedUnits{
863 FecCorrectedUnits: uint64(stats[FecCorrectedUnits]),
864 }
865 metrics.IsXgemKeyErrors = &extension.GetOnuCountersResponse_XgemKeyErrors{
866 XgemKeyErrors: uint64(stats[XGEMKeyErrors]),
867 }
868 metrics.IsXgemLoss = &extension.GetOnuCountersResponse_XgemLoss{
869 XgemLoss: uint64(stats[XGEMLoss]),
870 }
871 metrics.IsRxPloamsError = &extension.GetOnuCountersResponse_RxPloamsError{
872 RxPloamsError: uint64(stats[RxPloamsError]),
873 }
874 metrics.IsRxPloamsNonIdle = &extension.GetOnuCountersResponse_RxPloamsNonIdle{
875 RxPloamsNonIdle: uint64(stats[RxPloamsNonIdle]),
876 }
877 metrics.IsRxOmci = &extension.GetOnuCountersResponse_RxOmci{
878 RxOmci: uint64(stats[RxOmci]),
879 }
880 metrics.IsRxOmciPacketsCrcError = &extension.GetOnuCountersResponse_RxOmciPacketsCrcError{
881 RxOmciPacketsCrcError: uint64(stats[RxOmciPacketsCrcError]),
882 }
883 metrics.IsRxBytes = &extension.GetOnuCountersResponse_RxBytes{
884 RxBytes: uint64(stats[RxBytes]),
885 }
886 metrics.IsRxPackets = &extension.GetOnuCountersResponse_RxPackets{
887 RxPackets: uint64(stats[RxPackets]),
888 }
889 metrics.IsTxBytes = &extension.GetOnuCountersResponse_TxBytes{
890 TxBytes: uint64(stats[TxBytes]),
891 }
892 metrics.IsTxPackets = &extension.GetOnuCountersResponse_TxPackets{
893 TxPackets: uint64(stats[TxPackets]),
894 }
895 metrics.IsBerReported = &extension.GetOnuCountersResponse_BerReported{
896 BerReported: uint64(stats[BerReported]),
897 }
898 metrics.IsLcdgErrors = &extension.GetOnuCountersResponse_LcdgErrors{
899 LcdgErrors: uint64(stats[LcdgErrors]),
900 }
901 metrics.IsRdiErrors = &extension.GetOnuCountersResponse_RdiErrors{
902 RdiErrors: uint64(stats[RdiErrors]),
903 }
904 metrics.IsTimestamp = &extension.GetOnuCountersResponse_Timestamp{
905 Timestamp: uint32(stats[Timestamp]),
906 }
907
908 singleValResp.Response.Status = extension.GetValueResponse_OK
909 logger.Debugw(ctx, "updateGetOnuPonCountersResponse", log.Fields{"resp": singleValResp})
910}