blob: 2b91709b999db66a7b447ce378f546297f2f8b0b [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"
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +000024 "math"
Shrey Baid26912972020-04-16 21:02:31 +053025 "sync"
26 "time"
27
Mahir Gunyel85f61c12021-10-06 11:53:45 -070028 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040029 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
30
31 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Thomas Lee S94109f12020-03-03 16:39:29 +053032 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +053033 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoo106c61a2021-08-11 18:05:46 -040034 "github.com/opencord/voltha-protos/v5/go/extension"
35 "github.com/opencord/voltha-protos/v5/go/openolt"
36 "github.com/opencord/voltha-protos/v5/go/voltha"
Abhilash S.L765ad002019-04-24 16:40:57 +053037)
38
Gamze Abakafcbd6e72020-12-17 13:25:16 +000039const (
Akash Kankanala041a2122024-10-16 15:49:22 +053040 // NNIStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000041 NNIStats = "NNIStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053042 // PONStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000043 PONStats = "PONStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053044 // ONUStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000045 ONUStats = "ONUStats"
Akash Kankanala041a2122024-10-16 15:49:22 +053046 // GEMStats statType constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000047 GEMStats = "GEMStats"
48
Akash Kankanala041a2122024-10-16 15:49:22 +053049 // RxBytes constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000050 RxBytes = "RxBytes"
Akash Kankanala041a2122024-10-16 15:49:22 +053051 // RxPackets constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000052 RxPackets = "RxPackets"
Akash Kankanala041a2122024-10-16 15:49:22 +053053 // TxBytes constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000054 TxBytes = "TxBytes"
Akash Kankanala041a2122024-10-16 15:49:22 +053055 // TxPackets constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000056 TxPackets = "TxPackets"
Akash Kankanala041a2122024-10-16 15:49:22 +053057 // FecCodewords constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000058 FecCodewords = "FecCodewords"
Akash Kankanala041a2122024-10-16 15:49:22 +053059 // BipUnits constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000060 BipUnits = "BipUnits"
Akash Kankanala041a2122024-10-16 15:49:22 +053061 // BipErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000062 BipErrors = "BipErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053063 // RxPloamsNonIdle constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000064 RxPloamsNonIdle = "RxPloamsNonIdle"
Akash Kankanala041a2122024-10-16 15:49:22 +053065 // RxPloamsError constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000066 RxPloamsError = "RxPloamsError"
Akash Kankanala041a2122024-10-16 15:49:22 +053067 // RxOmci constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000068 RxOmci = "RxOmci"
Akash Kankanala041a2122024-10-16 15:49:22 +053069 // RxOmciPacketsCrcError constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000070 RxOmciPacketsCrcError = "RxOmciPacketsCrcError"
Akash Kankanala041a2122024-10-16 15:49:22 +053071 // PositiveDrift constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000072 PositiveDrift = "PositiveDrift"
Akash Kankanala041a2122024-10-16 15:49:22 +053073 // NegativeDrift constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000074 NegativeDrift = "NegativeDrift"
Akash Kankanala041a2122024-10-16 15:49:22 +053075 // DelimiterMissDetection constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000076 DelimiterMissDetection = "DelimiterMissDetection"
Akash Kankanala041a2122024-10-16 15:49:22 +053077 // FecCorrectedSymbols constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000078 FecCorrectedSymbols = "FecCorrectedSymbols"
Akash Kankanala041a2122024-10-16 15:49:22 +053079 // FecCodewordsCorrected constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000080 FecCodewordsCorrected = "FecCodewordsCorrected"
Akash Kankanala041a2122024-10-16 15:49:22 +053081 // fecCodewordsUncorrectable constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000082 fecCodewordsUncorrectable = "fec_codewords_uncorrectable"
Akash Kankanala041a2122024-10-16 15:49:22 +053083 // FecCorrectedUnits constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000084 FecCorrectedUnits = "FecCorrectedUnits"
Akash Kankanala041a2122024-10-16 15:49:22 +053085 // XGEMKeyErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000086 XGEMKeyErrors = "XGEMKeyErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053087 // XGEMLoss constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000088 XGEMLoss = "XGEMLOSS"
Akash Kankanala041a2122024-10-16 15:49:22 +053089 // BerReported constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000090 BerReported = "BerReported"
Akash Kankanala041a2122024-10-16 15:49:22 +053091 // LcdgErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000092 LcdgErrors = "LcdgErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053093 // RdiErrors constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +000094 RdiErrors = "RdiErrors"
Akash Kankanala041a2122024-10-16 15:49:22 +053095 // Timestamp constant
Himani Chawla2c8ae0f2021-05-18 23:27:00 +053096 Timestamp = "Timestamp"
Gamze Abakafcbd6e72020-12-17 13:25:16 +000097)
98
Naga Manjunath7615e552019-10-11 22:35:47 +053099var mutex = &sync.Mutex{}
100
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000101var onuStats = make(chan *openolt.OnuStatistics, 100)
102var gemStats = make(chan *openolt.GemPortStatistics, 100)
103
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400104// statRegInfo is used to register for notifications
105// on receiving port stats and flow stats indication
kesavand62126212021-01-12 04:56:06 -0500106type statRegInfo struct {
107 chn chan bool
108 portNo uint32
109 portType extension.GetOltPortCounters_PortType
110}
111
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112// PonPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530113type PonPort struct {
Abhilash S.L765ad002019-04-24 16:40:57 +0530114 ONUs map[uint32]interface{}
115 ONUsByID map[uint32]interface{}
116
Akash Kankanala041a2122024-10-16 15:49:22 +0530117 DeviceID string
118 Label string
119
akashreddyk302516f2025-11-17 15:18:44 +0530120 RxBytes uint64
121 RxPackets uint64
122 RxUcastPackets uint64
123 RxMcastPackets uint64
124 RxBcastPackets uint64
125 RxErrorPackets uint64
126 RxPacketsDropped uint64
127 TxBytes uint64
128 TxPackets uint64
129 TxUcastPackets uint64
130 TxMcastPackets uint64
131 TxBcastPackets uint64
132 TxErrorPackets uint64
133 TxDroppedTotal uint64
134 RxCrcErrors uint64
135 BipErrors uint64
Akash Kankanala041a2122024-10-16 15:49:22 +0530136 /*
137 This is a highly reduced version taken from the adtran pon_port.
138 TODO: Extend for use in the openolt adapter set.
139 */
140 /* MAX_ONUS_SUPPORTED = 256
141 DEFAULT_ENABLED = False
142 MAX_DEPLOYMENT_RANGE = 25000 # Meters (OLT-PB maximum)
143
144 _MCAST_ONU_ID = 253
145 _MCAST_ALLOC_BASE = 0x500
146
147 _SUPPORTED_ACTIVATION_METHODS = ['autodiscovery'] # , 'autoactivate']
148 _SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
149 */
150 PONID uint32
151 IntfID uint32
152 PortNum uint32
153 PortID uint32
Abhilash S.L765ad002019-04-24 16:40:57 +0530154}
155
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700156// NewPONPort returns a new instance of PonPort initialized with given PONID, DeviceID, IntfID and PortNum
Abhilash S.L765ad002019-04-24 16:40:57 +0530157func NewPONPort(PONID uint32, DeviceID string, IntfID uint32, PortNum uint32) *PonPort {
Abhilash S.L765ad002019-04-24 16:40:57 +0530158 var PON PonPort
159
160 PON.PONID = PONID
161 PON.DeviceID = DeviceID
162 PON.IntfID = IntfID
163 PON.PortNum = PortNum
164 PON.PortID = 0
Naga Manjunath7615e552019-10-11 22:35:47 +0530165 PON.Label = fmt.Sprintf("%s%d", "pon-", PONID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530166
167 PON.ONUs = make(map[uint32]interface{})
168 PON.ONUsByID = make(map[uint32]interface{})
169
170 /*
171 Statistics taken from nni_port
172 self.intf_id = 0 #handled by getter
173 self.port_no = 0 #handled by getter
174 self.port_id = 0 #handled by getter
175
176 Note: In the current implementation of the kpis coming from the BAL the stats are the
177 samne model for NNI and PON.
178
179 TODO: Integrate additional kpis for the PON and other southbound port objecgts.
180
181 */
182
183 PON.RxBytes = 0
184 PON.RxPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000185 PON.RxUcastPackets = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530186 PON.RxMcastPackets = 0
187 PON.RxBcastPackets = 0
188 PON.RxErrorPackets = 0
189 PON.TxBytes = 0
190 PON.TxPackets = 0
191 PON.TxUcastPackets = 0
192 PON.TxMcastPackets = 0
193 PON.TxBcastPackets = 0
194 PON.TxErrorPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000195 PON.RxCrcErrors = 0
196 PON.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530197
198 /* def __str__(self):
199 return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
200 self._admin_state,
201 self._oper_status,
202 self.olt)
203 */
204 return &PON
205}
206
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207// NniPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530208type NniPort struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530209 Name string
Abhilash S.L765ad002019-04-24 16:40:57 +0530210
akashreddyk302516f2025-11-17 15:18:44 +0530211 RxBytes uint64
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000212 RxFrames uint64
213 RxUcastFrames uint64
214 RxMcastFrames uint64
215 RxBcastFrames uint64
216 RxErrorFrames uint64
akashreddyk302516f2025-11-17 15:18:44 +0530217 RxPacketsDropped uint64
218 TxBytes uint64
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000219 TxFrames uint64
220 TxUcastFrames uint64
221 TxMcastFrames uint64
222 TxBcastFrames uint64
223 TxErrorFrames uint64
akashreddyk302516f2025-11-17 15:18:44 +0530224 TxDroppedTotal uint64
225 RxCrcErrors uint64
226 BipErrors uint64
Akash Kankanala041a2122024-10-16 15:49:22 +0530227 /*
228 Northbound network port, often Ethernet-based
229
230 This is a highly reduced version taken from the adtran nni_port code set
231 TODO: add functions to allow for port specific values and operations
232 */
233 PortNum uint32
234 LogicalPort uint32
235 IntfID uint32
Abhilash S.L765ad002019-04-24 16:40:57 +0530236}
237
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700238// NewNniPort returns a new instance of NniPort initialized with the given PortNum and IntfID
Abhilash S.L765ad002019-04-24 16:40:57 +0530239func NewNniPort(PortNum uint32, IntfID uint32) *NniPort {
Abhilash S.L765ad002019-04-24 16:40:57 +0530240 var NNI NniPort
241
242 NNI.PortNum = PortNum
Naga Manjunath7615e552019-10-11 22:35:47 +0530243 NNI.Name = fmt.Sprintf("%s%d", "nni-", PortNum)
Abhilash S.L765ad002019-04-24 16:40:57 +0530244 NNI.IntfID = IntfID
245
246 NNI.RxBytes = 0
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000247 NNI.RxFrames = 0
248 NNI.RxUcastFrames = 0
249 NNI.RxMcastFrames = 0
250 NNI.RxBcastFrames = 0
251 NNI.RxErrorFrames = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530252 NNI.TxBytes = 0
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000253 NNI.TxFrames = 0
254 NNI.TxUcastFrames = 0
255 NNI.TxMcastFrames = 0
256 NNI.TxBcastFrames = 0
257 NNI.TxErrorFrames = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000258 NNI.RxCrcErrors = 0
259 NNI.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530260
261 return &NNI
262}
263
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400264// StatType defines portStatsType and flowStatsType types
kesavand62126212021-01-12 04:56:06 -0500265type StatType int
266
267const (
268 portStatsType StatType = iota
269 flowStatsType
270)
271
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272// OpenOltStatisticsMgr structure
Abhilash S.L765ad002019-04-24 16:40:57 +0530273type OpenOltStatisticsMgr struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530274 Device *DeviceHandler
275 NorthBoundPort map[uint32]*NniPort
276 SouthBoundPort map[uint32]*PonPort
277 statIndListners map[StatType]*list.List
Abhilash S.L765ad002019-04-24 16:40:57 +0530278 // TODO PMMetrics Metrics
Akash Kankanala041a2122024-10-16 15:49:22 +0530279 // statIndListners is the list of requests to be notified when port and flow stats indication is received
kesavand62126212021-01-12 04:56:06 -0500280 statIndListnerMu sync.Mutex
Abhilash S.L765ad002019-04-24 16:40:57 +0530281}
282
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700283// NewOpenOltStatsMgr returns a new instance of the OpenOltStatisticsMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000284func NewOpenOltStatsMgr(ctx context.Context, Dev *DeviceHandler) *OpenOltStatisticsMgr {
Abhilash S.L765ad002019-04-24 16:40:57 +0530285 var StatMgr OpenOltStatisticsMgr
286
287 StatMgr.Device = Dev
288 // TODO call metric PMMetric =
289 // Northbound and Southbound ports
290 // added to initialize the pm_metrics
291 var Ports interface{}
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530292 NumNniPorts := Dev.resourceMgr[0].DevInfo.GetNniPorts()
293 Ports, _ = InitPorts(ctx, "nni", Dev.device.Id, NumNniPorts)
Naga Manjunath7615e552019-10-11 22:35:47 +0530294 StatMgr.NorthBoundPort, _ = Ports.(map[uint32]*NniPort)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700295 NumPonPorts := Dev.resourceMgr[0].DevInfo.GetPonPorts()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000296 Ports, _ = InitPorts(ctx, "pon", Dev.device.Id, NumPonPorts)
Naga Manjunath7615e552019-10-11 22:35:47 +0530297 StatMgr.SouthBoundPort, _ = Ports.(map[uint32]*PonPort)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000298 if StatMgr.Device.openOLT.enableONUStats {
299 go StatMgr.publishOnuStats()
300 }
301 if StatMgr.Device.openOLT.enableGemStats {
302 go StatMgr.publishGemStats()
303 }
kesavand62126212021-01-12 04:56:06 -0500304 StatMgr.statIndListners = make(map[StatType]*list.List)
305 StatMgr.statIndListners[portStatsType] = list.New()
306 StatMgr.statIndListners[flowStatsType] = list.New()
Abhilash S.L765ad002019-04-24 16:40:57 +0530307 return &StatMgr
308}
309
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700310// 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 +0000311func InitPorts(ctx context.Context, Intftype string, DeviceID string, numOfPorts uint32) (interface{}, error) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530312 /*
313 This method collects the port objects: nni and pon that are updated with the
314 current data from the OLT
315
316 Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
317 and NOT the port number. When the port object is instantiated it will contain the intf_id and
318 port_no values
319
320 :param type:
321 :return:
322 */
323 var i uint32
mgouda86543582025-10-29 20:58:16 +0530324 switch Intftype {
325 case "nni":
Naga Manjunath7615e552019-10-11 22:35:47 +0530326 NniPorts := make(map[uint32]*NniPort)
327 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000328 Port := BuildPortObject(ctx, i, "nni", DeviceID).(*NniPort)
Naga Manjunath7615e552019-10-11 22:35:47 +0530329 NniPorts[Port.IntfID] = Port
Abhilash S.L765ad002019-04-24 16:40:57 +0530330 }
331 return NniPorts, nil
mgouda86543582025-10-29 20:58:16 +0530332 case "pon":
Naga Manjunath7615e552019-10-11 22:35:47 +0530333 PONPorts := make(map[uint32]*PonPort)
334 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 PONPort := BuildPortObject(ctx, i, "pon", DeviceID).(*PonPort)
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700336 PONPorts[plt.PortNoToIntfID(PONPort.IntfID, voltha.Port_PON_OLT)] = PONPort
Abhilash S.L765ad002019-04-24 16:40:57 +0530337 }
338 return PONPorts, nil
mgouda86543582025-10-29 20:58:16 +0530339 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000340 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"interface-type": Intftype})
Thomas Lee S94109f12020-03-03 16:39:29 +0530341 return nil, olterrors.NewErrInvalidValue(log.Fields{"interface-type": Intftype}, nil)
Abhilash S.L765ad002019-04-24 16:40:57 +0530342 }
343}
344
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700345// BuildPortObject allows for updating north and southbound ports, newly discovered ports, and devices
Neha Sharma96b7bf22020-06-15 10:37:32 +0000346func BuildPortObject(ctx context.Context, PortNum uint32, IntfType string, DeviceID string) interface{} {
Abhilash S.L765ad002019-04-24 16:40:57 +0530347 /*
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700348 Separate method to allow for updating north and southbound ports
Abhilash S.L765ad002019-04-24 16:40:57 +0530349 newly discovered ports and devices
350
351 :param port_num:
352 :param type:
353 :return:
354 */
355
Akash Kankanala041a2122024-10-16 15:49:22 +0530356 // This builds a port object which is added to the
357 // appropriate northbound or southbound values
mgouda86543582025-10-29 20:58:16 +0530358 switch IntfType {
359 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700360 IntfID := plt.IntfIDToPortNo(PortNum, voltha.Port_ETHERNET_NNI)
361 nniID := plt.PortNoToIntfID(IntfID, voltha.Port_ETHERNET_NNI)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000362 logger.Debugw(ctx, "interface-type-nni",
Shrey Baid26912972020-04-16 21:02:31 +0530363 log.Fields{
364 "nni-id": nniID,
365 "intf-type": IntfType})
Naga Manjunath7615e552019-10-11 22:35:47 +0530366 return NewNniPort(PortNum, nniID)
mgouda86543582025-10-29 20:58:16 +0530367 case "pon":
Abhilash S.L765ad002019-04-24 16:40:57 +0530368 // PON ports require a different configuration
369 // intf_id and pon_id are currently equal.
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700370 IntfID := plt.IntfIDToPortNo(PortNum, voltha.Port_PON_OLT)
371 PONID := plt.PortNoToIntfID(IntfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000372 logger.Debugw(ctx, "interface-type-pon",
Shrey Baid26912972020-04-16 21:02:31 +0530373 log.Fields{
374 "pon-id": PONID,
375 "intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530376 return NewPONPort(PONID, DeviceID, IntfID, PortNum)
mgouda86543582025-10-29 20:58:16 +0530377 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000378 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530379 return nil
380 }
381}
382
Naga Manjunath7615e552019-10-11 22:35:47 +0530383// collectNNIMetrics will collect the nni port metrics
384func (StatMgr *OpenOltStatisticsMgr) collectNNIMetrics(nniID uint32) map[string]float32 {
Naga Manjunath7615e552019-10-11 22:35:47 +0530385 nnival := make(map[string]float32)
386 mutex.Lock()
387 cm := StatMgr.Device.portStats.NorthBoundPort[nniID]
388 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000389 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530390
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000391 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400392 for metric := range metricNames {
393 if metricNames[metric].Enabled {
394 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530395 }
396 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000397
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530398 if cm != nil {
399 for _, mName := range metrics {
400 switch mName {
401 case "rx_bytes":
402 nnival["RxBytes"] = float32(cm.RxBytes)
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000403 case "rx_frames":
404 nnival["RxFrames"] = float32(cm.RxFrames)
405 case "rx_ucast_frames":
406 nnival["RxUcastFrames"] = float32(cm.RxUcastFrames)
407 case "rx_mcast_frames":
408 nnival["RxMcastFrames"] = float32(cm.RxMcastFrames)
409 case "rx_bcast_frames":
410 nnival["RxBcastFrames"] = float32(cm.RxBcastFrames)
411 case "rx_error_frames":
412 nnival["RxErrorFrames"] = float32(cm.RxErrorFrames)
akashreddyk302516f2025-11-17 15:18:44 +0530413 case "rx_crc_errors":
414 nnival["RxCrcErrors"] = float32(cm.RxCrcErrors)
415 case "rx_packets_dropped":
416 nnival["RxPacketsDropped"] = float32(cm.RxPacketsDropped)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530417 case "tx_bytes":
418 nnival["TxBytes"] = float32(cm.TxBytes)
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000419 case "tx_frames":
420 nnival["TxFrames"] = float32(cm.TxFrames)
421 case "tx_ucast_frames":
422 nnival["TxUcastFrames"] = float32(cm.TxUcastFrames)
423 case "tx_mcast_frames":
424 nnival["TxMcastFrames"] = float32(cm.TxMcastFrames)
425 case "tx_bcast_frames":
426 nnival["TxBcastFrames"] = float32(cm.TxBcastFrames)
akashreddyk302516f2025-11-17 15:18:44 +0530427 case "tx_dropped_total":
428 nnival["TxDroppedTotal"] = float32(cm.TxDroppedTotal)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530429 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000430 }
431 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530432 return nnival
433}
434
435// collectPONMetrics will collect the pon port metrics
436func (StatMgr *OpenOltStatisticsMgr) collectPONMetrics(pID uint32) map[string]float32 {
Naga Manjunath7615e552019-10-11 22:35:47 +0530437 ponval := make(map[string]float32)
438 mutex.Lock()
439 cm := StatMgr.Device.portStats.SouthBoundPort[pID]
440 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000441 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530442
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000443 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400444 for metric := range metricNames {
445 if metricNames[metric].Enabled {
446 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530447 }
448 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000449
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530450 if cm != nil {
451 for _, mName := range metrics {
452 switch mName {
453 case "rx_bytes":
454 ponval["RxBytes"] = float32(cm.RxBytes)
455 case "rx_packets":
456 ponval["RxPackets"] = float32(cm.RxPackets)
457 case "rx_ucast_packets":
458 ponval["RxUcastPackets"] = float32(cm.RxUcastPackets)
459 case "rx_mcast_packets":
460 ponval["RxMcastPackets"] = float32(cm.RxMcastPackets)
461 case "rx_bcast_packets":
462 ponval["RxBcastPackets"] = float32(cm.RxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530463 case "rx_error_packets":
464 ponval["RxErrorPackets"] = float32(cm.RxErrorPackets)
465 case "rx_packets_dropped":
466 ponval["RxPacketsDropped"] = float32(cm.RxPacketsDropped)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530467 case "tx_bytes":
468 ponval["TxBytes"] = float32(cm.TxBytes)
469 case "tx_packets":
470 ponval["TxPackets"] = float32(cm.TxPackets)
471 case "tx_mcast_packets":
472 ponval["TxMcastPackets"] = float32(cm.TxMcastPackets)
473 case "tx_bcast_packets":
474 ponval["TxBcastPackets"] = float32(cm.TxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530475 case "tx_error_packets":
476 ponval["TxErrorPackets"] = float32(cm.TxErrorPackets)
477 case "tx_dropped_total":
478 ponval["TxDroppedTotal"] = float32(cm.TxDroppedTotal)
Sridhar Ravindra0f57ac12025-10-27 20:22:11 +0530479 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000480 }
481 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530482 return ponval
483}
484
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000485// converGemStats will convert gem stats response to kpi context
486func (StatMgr *OpenOltStatisticsMgr) convertGemStats(gemStats *openolt.GemPortStatistics) map[string]float32 {
487 gemStatsVal := make(map[string]float32)
488 gemStatsVal[IntfID] = float32(gemStats.IntfId)
489 gemStatsVal[GemID] = float32(gemStats.GemportId)
490 gemStatsVal[RxPackets] = float32(gemStats.RxPackets)
491 gemStatsVal[RxBytes] = float32(gemStats.RxBytes)
492 gemStatsVal[TxPackets] = float32(gemStats.TxPackets)
493 gemStatsVal[TxBytes] = float32(gemStats.TxBytes)
494 return gemStatsVal
495}
496
497// convertONUStats will convert onu stats response to kpi context
498func (StatMgr *OpenOltStatisticsMgr) convertONUStats(onuStats *openolt.OnuStatistics) map[string]float32 {
499 onuStatsVal := make(map[string]float32)
500 onuStatsVal[IntfID] = float32(onuStats.IntfId)
501 onuStatsVal[OnuID] = float32(onuStats.OnuId)
502 onuStatsVal[PositiveDrift] = float32(onuStats.PositiveDrift)
503 onuStatsVal[NegativeDrift] = float32(onuStats.NegativeDrift)
504 onuStatsVal[DelimiterMissDetection] = float32(onuStats.DelimiterMissDetection)
505 onuStatsVal[BipErrors] = float32(onuStats.BipErrors)
506 onuStatsVal[BipUnits] = float32(onuStats.BipUnits)
507 onuStatsVal[FecCorrectedSymbols] = float32(onuStats.FecCorrectedSymbols)
508 onuStatsVal[FecCodewordsCorrected] = float32(onuStats.FecCodewordsCorrected)
509 onuStatsVal[fecCodewordsUncorrectable] = float32(onuStats.FecCodewordsUncorrectable)
510 onuStatsVal[FecCodewords] = float32(onuStats.FecCodewords)
511 onuStatsVal[FecCorrectedUnits] = float32(onuStats.FecCorrectedUnits)
512 onuStatsVal[XGEMKeyErrors] = float32(onuStats.XgemKeyErrors)
513 onuStatsVal[XGEMLoss] = float32(onuStats.XgemLoss)
514 onuStatsVal[RxPloamsError] = float32(onuStats.RxPloamsError)
515 onuStatsVal[RxPloamsNonIdle] = float32(onuStats.RxPloamsNonIdle)
516 onuStatsVal[RxOmci] = float32(onuStats.RxOmci)
517 onuStatsVal[RxOmciPacketsCrcError] = float32(onuStats.RxOmciPacketsCrcError)
518 onuStatsVal[RxBytes] = float32(onuStats.RxBytes)
519 onuStatsVal[RxPackets] = float32(onuStats.RxPackets)
520 onuStatsVal[TxBytes] = float32(onuStats.TxBytes)
521 onuStatsVal[TxPackets] = float32(onuStats.TxPackets)
522 onuStatsVal[BerReported] = float32(onuStats.BerReported)
523 onuStatsVal[LcdgErrors] = float32(onuStats.LcdgErrors)
524 onuStatsVal[RdiErrors] = float32(onuStats.RdiErrors)
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530525 onuStatsVal[Timestamp] = float32(onuStats.Timestamp)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000526 return onuStatsVal
527}
528
529// collectOnuStats will collect the onu metrics
530func (StatMgr *OpenOltStatisticsMgr) collectOnuStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
531 onu := &openolt.Onu{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID}
532 logger.Debugw(ctx, "pulling-onu-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID})
bseenivaa1622112025-12-11 18:24:02 +0530533 subCtx, cancel := context.WithTimeout(context.Background(), StatMgr.Device.openOLT.rpcTimeout)
534 defer cancel()
535 if stats, err := StatMgr.Device.Client.GetOnuStatistics(subCtx, onu); err == nil {
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000536 onuStats <- stats
537 } else {
538 logger.Errorw(ctx, "error-while-getting-onu-stats-for-onu", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "err": err})
539 }
540}
541
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530542// collectOnDemandOnuStats will collect the onui-pon metrics
543func (StatMgr *OpenOltStatisticsMgr) collectOnDemandOnuStats(ctx context.Context, intfID uint32, onuID uint32) map[string]float32 {
544 onu := &openolt.Onu{IntfId: intfID, OnuId: onuID}
545 var stats *openolt.OnuStatistics
546 var err error
547 logger.Debugw(ctx, "pulling-onu-stats-on-demand", log.Fields{"IntfID": intfID, "OnuID": onuID})
bseenivaa1622112025-12-11 18:24:02 +0530548 subCtx, cancel := context.WithTimeout(context.Background(), StatMgr.Device.openOLT.rpcTimeout)
549 if stats, err = StatMgr.Device.Client.GetOnuStatistics(subCtx, onu); err == nil {
550 cancel()
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530551 statValue := StatMgr.convertONUStats(stats)
552 return statValue
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530553 }
bseenivaa1622112025-12-11 18:24:02 +0530554 cancel()
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530555 logger.Errorw(ctx, "error-while-getting-onu-stats-for-onu", log.Fields{"IntfID": intfID, "OnuID": onuID, "err": err})
556 return nil
557}
558
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000559// collectOnuAndGemStats will collect both onu and gem metrics
560func (StatMgr *OpenOltStatisticsMgr) collectOnuAndGemStats(ctx context.Context, onuGemInfo []rsrcMgr.OnuGemInfo) {
561 if !StatMgr.Device.openOLT.enableONUStats && !StatMgr.Device.openOLT.enableGemStats {
562 return
563 }
564
565 for _, onuInfo := range onuGemInfo {
566 if StatMgr.Device.openOLT.enableONUStats {
567 go StatMgr.collectOnuStats(ctx, onuInfo)
568 }
569 if StatMgr.Device.openOLT.enableGemStats {
570 go StatMgr.collectGemStats(ctx, onuInfo)
571 }
572 }
573}
574
575// collectGemStats will collect gem metrics
576func (StatMgr *OpenOltStatisticsMgr) collectGemStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
577 for _, gem := range onuGemInfo.GemPorts {
578 logger.Debugw(ctx, "pulling-gem-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem})
579 onuPacket := &openolt.OnuPacket{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID, GemportId: gem}
bseenivaa1622112025-12-11 18:24:02 +0530580 subCtx, cancel := context.WithTimeout(context.Background(), StatMgr.Device.openOLT.rpcTimeout)
581 if stats, err := StatMgr.Device.Client.GetGemPortStatistics(subCtx, onuPacket); err == nil {
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000582 gemStats <- stats
583 } else {
584 logger.Errorw(ctx, "error-while-getting-gem-stats-for-onu",
585 log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem, "err": err})
586 }
bseenivaa1622112025-12-11 18:24:02 +0530587 cancel()
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000588 }
589}
590
591// publishGemStats will publish the gem metrics
592func (StatMgr *OpenOltStatisticsMgr) publishGemStats() {
593 for {
594 statValue := StatMgr.convertGemStats(<-gemStats)
595 StatMgr.publishMetrics(context.Background(), GEMStats, statValue, &voltha.Port{Label: "GEM"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
596 }
597}
598
599// publishOnuStats will publish the onu metrics
600func (StatMgr *OpenOltStatisticsMgr) publishOnuStats() {
601 for {
602 statValue := StatMgr.convertONUStats(<-onuStats)
603 StatMgr.publishMetrics(context.Background(), ONUStats, statValue, &voltha.Port{Label: "ONU"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
604 }
605}
606
607// publishMetrics will publish the pon port metrics
kesavand62126212021-01-12 04:56:06 -0500608func (StatMgr *OpenOltStatisticsMgr) publishMetrics(ctx context.Context, statType string, val map[string]float32,
Girish Gowdra34815db2020-05-11 17:18:04 -0700609 port *voltha.Port, devID string, devType string) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 logger.Debugw(ctx, "publish-metrics",
Shrey Baid26912972020-04-16 21:02:31 +0530611 log.Fields{
612 "port": port.Label,
613 "metrics": val})
Naga Manjunath7615e552019-10-11 22:35:47 +0530614
615 var metricInfo voltha.MetricInformation
616 var ke voltha.KpiEvent2
Esin Karamanccb714b2019-11-29 15:02:06 +0000617 var volthaEventSubCatgry voltha.EventSubCategory_Types
Girish Gowdra34815db2020-05-11 17:18:04 -0700618 metricsContext := make(map[string]string)
619 metricsContext["oltid"] = devID
620 metricsContext["devicetype"] = devType
621 metricsContext["portlabel"] = port.Label
Naga Manjunath7615e552019-10-11 22:35:47 +0530622
mgouda86543582025-10-29 20:58:16 +0530623 switch statType {
624 case NNIStats:
Naga Manjunath7615e552019-10-11 22:35:47 +0530625 volthaEventSubCatgry = voltha.EventSubCategory_NNI
mgouda86543582025-10-29 20:58:16 +0530626 case PONStats:
Naga Manjunath7615e552019-10-11 22:35:47 +0530627 volthaEventSubCatgry = voltha.EventSubCategory_PON
mgouda86543582025-10-29 20:58:16 +0530628 case GEMStats, ONUStats:
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000629 volthaEventSubCatgry = voltha.EventSubCategory_ONT
Naga Manjunath7615e552019-10-11 22:35:47 +0530630 }
631
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700632 raisedTs := time.Now().Unix()
Naga Manjunath7615e552019-10-11 22:35:47 +0530633 mmd := voltha.MetricMetaData{
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000634 Title: statType,
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700635 Ts: float64(raisedTs),
Girish Gowdra34815db2020-05-11 17:18:04 -0700636 Context: metricsContext,
Naga Manjunath7615e552019-10-11 22:35:47 +0530637 DeviceId: devID,
638 }
639
640 metricInfo.Metadata = &mmd
641 metricInfo.Metrics = val
642
643 ke.SliceData = []*voltha.MetricInformation{&metricInfo}
644 ke.Type = voltha.KpiEventType_slice
Girish Gowdrac1b9d5e2021-04-22 12:47:44 -0700645 ke.Ts = float64(raisedTs)
Naga Manjunath7615e552019-10-11 22:35:47 +0530646
Himani Chawla473496d2021-12-01 00:10:30 +0530647 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 +0000648 logger.Errorw(ctx, "failed-to-send-stats", log.Fields{"err": err})
Naga Manjunath7615e552019-10-11 22:35:47 +0530649 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530650}
651
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700652// PortStatisticsIndication handles the port statistics indication
Akash Reddy Kankanalac6b6ca12025-06-12 14:26:57 +0530653func (StatMgr *OpenOltStatisticsMgr) PortStatisticsIndication(ctx context.Context, PortStats *common.PortStatistics, NumPonPorts uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000654 StatMgr.PortsStatisticsKpis(ctx, PortStats, NumPonPorts)
655 logger.Debugw(ctx, "received-port-stats-indication", log.Fields{"port-stats": PortStats})
Akash Kankanala041a2122024-10-16 15:49:22 +0530656 // Indicate that PortStatisticsIndication is handled
657 // PortStats.IntfId is actually the port number
kesavand62126212021-01-12 04:56:06 -0500658 StatMgr.processStatIndication(ctx, portStatsType, PortStats.IntfId)
Abhilash S.L765ad002019-04-24 16:40:57 +0530659 // TODO send stats to core topic to the voltha kafka or a different kafka ?
660}
661
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700662// FlowStatisticsIndication to be implemented
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663func FlowStatisticsIndication(ctx context.Context, self, FlowStats *openolt.FlowStatistics) {
664 logger.Debugw(ctx, "flow-stats-collected", log.Fields{"flow-stats": FlowStats})
Akash Kankanala041a2122024-10-16 15:49:22 +0530665 // TODO send to kafka ?
Abhilash S.L765ad002019-04-24 16:40:57 +0530666}
667
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700668// 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 +0530669func (StatMgr *OpenOltStatisticsMgr) PortsStatisticsKpis(ctx context.Context, PortStats *common.PortStatistics, NumPonPorts uint32) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530670 /*map the port stats values into a dictionary
671 Create a kpoEvent and publish to Kafka
672
673 :param port_stats:
674 :return:
675 */
Akash Kankanala041a2122024-10-16 15:49:22 +0530676 // var err error
Abhilash S.L765ad002019-04-24 16:40:57 +0530677 IntfID := PortStats.IntfId
678
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000679 if (IntfID & plt.IntfIDToPortNo(0, voltha.Port_ETHERNET_NNI)) != 0 {
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
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000684 portNNIStat.RxFrames = selectCounter(PortStats.RxFrames, PortStats.RxPackets)
685 portNNIStat.RxUcastFrames = selectCounter(PortStats.RxUcastFrames, PortStats.RxUcastPackets)
686 portNNIStat.RxMcastFrames = selectCounter(PortStats.RxMcastFrames, PortStats.RxMcastPackets)
687 portNNIStat.RxBcastFrames = selectCounter(PortStats.RxBcastFrames, PortStats.RxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530688 portNNIStat.RxCrcErrors = PortStats.RxCrcErrors
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000689 portNNIStat.RxErrorFrames = selectCounter(PortStats.RxErrorFrames, PortStats.RxErrorPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530690 portNNIStat.RxPacketsDropped = PortStats.RxPacketsDropped
Naga Manjunath7615e552019-10-11 22:35:47 +0530691 portNNIStat.TxBytes = PortStats.TxBytes
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000692 portNNIStat.TxFrames = selectCounter(PortStats.TxFrames, PortStats.TxPackets)
693 portNNIStat.TxUcastFrames = selectCounter(PortStats.TxUcastFrames, PortStats.TxUcastPackets)
694 portNNIStat.TxMcastFrames = selectCounter(PortStats.TxMcastFrames, PortStats.TxMcastPackets)
695 portNNIStat.TxBcastFrames = selectCounter(PortStats.TxBcastFrames, PortStats.TxBcastPackets)
696 portNNIStat.TxErrorFrames = selectCounter(PortStats.TxErrorFrames, PortStats.TxErrorPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530697 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}
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000911
912func selectCounter(primary, secondary uint64) uint64 {
913 if isValidCounter(primary) {
914 return primary
915 }
916 if isValidCounter(secondary) {
917 return secondary
918 }
919 return 0
920}
921
922func isValidCounter(metric uint64) bool {
923 return metric != 0 && metric != math.MaxUint64
924}