blob: 429ec11e4e4dfc6419ed112ac9a5a14c560d2e5f [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
akashreddyk3ca7c212026-02-05 09:57:53 +0530677 logicalPortNo := PortStats.IntfId
Abhilash S.L765ad002019-04-24 16:40:57 +0530678
akashreddyk3ca7c212026-02-05 09:57:53 +0530679 if plt.IntfIDToPortTypeName(logicalPortNo) == voltha.Port_ETHERNET_NNI {
680 IntfID, err := plt.IntfIDFromNniPortNum(ctx, logicalPortNo)
681 if err != nil {
682 return
683 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530684 var portNNIStat NniPort
685 portNNIStat.IntfID = IntfID
akashreddyk3ca7c212026-02-05 09:57:53 +0530686 portNNIStat.PortNum = logicalPortNo
Naga Manjunath7615e552019-10-11 22:35:47 +0530687 portNNIStat.RxBytes = PortStats.RxBytes
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000688 portNNIStat.RxFrames = selectCounter(PortStats.RxFrames, PortStats.RxPackets)
689 portNNIStat.RxUcastFrames = selectCounter(PortStats.RxUcastFrames, PortStats.RxUcastPackets)
690 portNNIStat.RxMcastFrames = selectCounter(PortStats.RxMcastFrames, PortStats.RxMcastPackets)
691 portNNIStat.RxBcastFrames = selectCounter(PortStats.RxBcastFrames, PortStats.RxBcastPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530692 portNNIStat.RxCrcErrors = PortStats.RxCrcErrors
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000693 portNNIStat.RxErrorFrames = selectCounter(PortStats.RxErrorFrames, PortStats.RxErrorPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530694 portNNIStat.RxPacketsDropped = PortStats.RxPacketsDropped
Naga Manjunath7615e552019-10-11 22:35:47 +0530695 portNNIStat.TxBytes = PortStats.TxBytes
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000696 portNNIStat.TxFrames = selectCounter(PortStats.TxFrames, PortStats.TxPackets)
697 portNNIStat.TxUcastFrames = selectCounter(PortStats.TxUcastFrames, PortStats.TxUcastPackets)
698 portNNIStat.TxMcastFrames = selectCounter(PortStats.TxMcastFrames, PortStats.TxMcastPackets)
699 portNNIStat.TxBcastFrames = selectCounter(PortStats.TxBcastFrames, PortStats.TxBcastPackets)
700 portNNIStat.TxErrorFrames = selectCounter(PortStats.TxErrorFrames, PortStats.TxErrorPackets)
akashreddyk302516f2025-11-17 15:18:44 +0530701 portNNIStat.TxDroppedTotal = PortStats.TxDroppedTotal
Naga Manjunath7615e552019-10-11 22:35:47 +0530702 mutex.Lock()
akashreddyk3ca7c212026-02-05 09:57:53 +0530703 StatMgr.NorthBoundPort[IntfID] = &portNNIStat
Naga Manjunath7615e552019-10-11 22:35:47 +0530704 mutex.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000705 logger.Debugw(ctx, "received-nni-stats", log.Fields{"nni-stats": StatMgr.NorthBoundPort})
Naga Manjunath7615e552019-10-11 22:35:47 +0530706 }
akashreddyk3ca7c212026-02-05 09:57:53 +0530707 if plt.IntfIDToPortTypeName(logicalPortNo) == voltha.Port_PON_OLT {
708 var portPonStat PonPort
709 ponID, err := plt.IntfIDFromPonPortNum(ctx, logicalPortNo)
710 if err != nil {
711 return
Naga Manjunath7615e552019-10-11 22:35:47 +0530712 }
akashreddyk3ca7c212026-02-05 09:57:53 +0530713 portPonStat.IntfID = ponID
714 portPonStat.PortNum = logicalPortNo
715 portPonStat.PONID = logicalPortNo
716 portPonStat.RxBytes = PortStats.RxBytes
717 portPonStat.RxPackets = PortStats.RxPackets
718 portPonStat.RxUcastPackets = PortStats.RxUcastPackets
719 portPonStat.RxMcastPackets = PortStats.RxMcastPackets
720 portPonStat.RxBcastPackets = PortStats.RxBcastPackets
721 portPonStat.RxErrorPackets = PortStats.RxErrorPackets
722 portPonStat.RxPacketsDropped = PortStats.RxPacketsDropped
723 portPonStat.TxBytes = PortStats.TxBytes
724 portPonStat.TxPackets = PortStats.TxPackets
725 portPonStat.TxUcastPackets = PortStats.TxUcastPackets
726 portPonStat.TxMcastPackets = PortStats.TxMcastPackets
727 portPonStat.TxBcastPackets = PortStats.TxBcastPackets
728 portPonStat.TxErrorPackets = PortStats.TxErrorPackets
729 portPonStat.TxDroppedTotal = PortStats.TxDroppedTotal
730 mutex.Lock()
731 StatMgr.SouthBoundPort[ponID] = &portPonStat
732 mutex.Unlock()
733 logger.Debugw(ctx, "received-pon-stats-for-port", log.Fields{"port-pon-stats": portPonStat})
Naga Manjunath7615e552019-10-11 22:35:47 +0530734 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700735 /*
736 Based upon the intf_id map to an nni port or a pon port
737 the intf_id is the key to the north or south bound collections
738
739 Based upon the intf_id the port object (nni_port or pon_port) will
740 have its data attr. updated by the current dataset collected.
741
742 For prefixing the rule is currently to use the port number and not the intf_id
743 */
Akash Kankanala041a2122024-10-16 15:49:22 +0530744 // FIXME : Just use first NNI for now
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700745 /* TODO should the data be marshaled before sending it ?
746 if IntfID == IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) {
747 //NNI port (just the first one)
748 err = UpdatePortObjectKpiData(StatMgr.NorthBoundPorts[PortStats.IntfID], PMData)
749 } else {
750 //PON ports
751 err = UpdatePortObjectKpiData(SouthboundPorts[PortStats.IntfID], PMData)
752 }
753 if (err != nil) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Error(ctx, "Error publishing statistics data")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700755 }
756 */
Abhilash S.L765ad002019-04-24 16:40:57 +0530757}
kesavand62126212021-01-12 04:56:06 -0500758
759func (StatMgr *OpenOltStatisticsMgr) updateGetOltPortCountersResponse(ctx context.Context, singleValResp *extension.SingleGetValueResponse, stats map[string]float32) {
kesavand62126212021-01-12 04:56:06 -0500760 metrics := singleValResp.GetResponse().GetPortCoutners()
761 metrics.TxBytes = uint64(stats["TxBytes"])
762 metrics.RxBytes = uint64(stats["RxBytes"])
763 metrics.TxPackets = uint64(stats["TxPackets"])
764 metrics.RxPackets = uint64(stats["RxPackets"])
765 metrics.TxErrorPackets = uint64(stats["TxErrorPackets"])
766 metrics.RxErrorPackets = uint64(stats["RxErrorPackets"])
767 metrics.TxBcastPackets = uint64(stats["TxBcastPackets"])
768 metrics.RxBcastPackets = uint64(stats["RxBcastPackets"])
769 metrics.TxUcastPackets = uint64(stats["TxUcastPackets"])
770 metrics.RxUcastPackets = uint64(stats["RxUcastPackets"])
771 metrics.TxMcastPackets = uint64(stats["TxMcastPackets"])
772 metrics.RxMcastPackets = uint64(stats["RxMcastPackets"])
773
774 singleValResp.Response.Status = extension.GetValueResponse_OK
775 logger.Debugw(ctx, "updateGetOltPortCountersResponse", log.Fields{"resp": singleValResp})
776}
777
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400778// RegisterForStatIndication registers ch as a channel on which indication is sent when statistics of type t is received
kesavand62126212021-01-12 04:56:06 -0500779func (StatMgr *OpenOltStatisticsMgr) RegisterForStatIndication(ctx context.Context, t StatType, ch chan bool, portNo uint32, portType extension.GetOltPortCounters_PortType) {
780 statInd := statRegInfo{
781 chn: ch,
782 portNo: portNo,
783 portType: portType,
784 }
785
786 logger.Debugf(ctx, "RegisterForStatIndication stat type %v portno %v porttype %v chan %v", t, portNo, portType, ch)
787 StatMgr.statIndListnerMu.Lock()
788 StatMgr.statIndListners[t].PushBack(statInd)
789 StatMgr.statIndListnerMu.Unlock()
kesavand62126212021-01-12 04:56:06 -0500790}
791
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400792// DeRegisterFromStatIndication removes the previously registered channel ch for type t of statistics
kesavand62126212021-01-12 04:56:06 -0500793func (StatMgr *OpenOltStatisticsMgr) DeRegisterFromStatIndication(ctx context.Context, t StatType, ch chan bool) {
794 StatMgr.statIndListnerMu.Lock()
795 defer StatMgr.statIndListnerMu.Unlock()
796
797 for e := StatMgr.statIndListners[t].Front(); e != nil; e = e.Next() {
798 statInd := e.Value.(statRegInfo)
799 if statInd.chn == ch {
800 StatMgr.statIndListners[t].Remove(e)
801 return
802 }
803 }
804}
805
806func (StatMgr *OpenOltStatisticsMgr) processStatIndication(ctx context.Context, t StatType, portNo uint32) {
807 var deRegList []*list.Element
808 var statInd statRegInfo
809
810 StatMgr.statIndListnerMu.Lock()
811 defer StatMgr.statIndListnerMu.Unlock()
812
813 if StatMgr.statIndListners[t] == nil || StatMgr.statIndListners[t].Len() == 0 {
814 logger.Debugf(ctx, "processStatIndication %v list is empty ", t)
815 return
816 }
817
818 for e := StatMgr.statIndListners[t].Front(); e != nil; e = e.Next() {
819 statInd = e.Value.(statRegInfo)
820 if statInd.portNo != portNo {
821 fmt.Printf("Skipping %v\n", e.Value)
822 continue
823 }
824 // message sent
825 statInd.chn <- true
826 deRegList = append(deRegList, e)
kesavand62126212021-01-12 04:56:06 -0500827 }
828 for _, e := range deRegList {
829 StatMgr.statIndListners[t].Remove(e)
830 }
kesavand62126212021-01-12 04:56:06 -0500831}
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530832
833func (StatMgr *OpenOltStatisticsMgr) updateGetOnuPonCountersResponse(ctx context.Context, singleValResp *extension.SingleGetValueResponse, stats map[string]float32) {
Himani Chawla2c8ae0f2021-05-18 23:27:00 +0530834 metrics := singleValResp.GetResponse().GetOnuPonCounters()
835 metrics.IsIntfId = &extension.GetOnuCountersResponse_IntfId{
836 IntfId: uint32(stats[IntfID]),
837 }
838 metrics.IsOnuId = &extension.GetOnuCountersResponse_OnuId{
839 OnuId: uint32(stats[OnuID]),
840 }
841 metrics.IsPositiveDrift = &extension.GetOnuCountersResponse_PositiveDrift{
842 PositiveDrift: uint64(stats[PositiveDrift]),
843 }
844 metrics.IsNegativeDrift = &extension.GetOnuCountersResponse_NegativeDrift{
845 NegativeDrift: uint64(stats[NegativeDrift]),
846 }
847 metrics.IsDelimiterMissDetection = &extension.GetOnuCountersResponse_DelimiterMissDetection{
848 DelimiterMissDetection: uint64(stats[DelimiterMissDetection]),
849 }
850 metrics.IsBipErrors = &extension.GetOnuCountersResponse_BipErrors{
851 BipErrors: uint64(stats[BipErrors]),
852 }
853 metrics.IsBipUnits = &extension.GetOnuCountersResponse_BipUnits{
854 BipUnits: uint64(stats[BipUnits]),
855 }
856 metrics.IsFecCorrectedSymbols = &extension.GetOnuCountersResponse_FecCorrectedSymbols{
857 FecCorrectedSymbols: uint64(stats[FecCorrectedSymbols]),
858 }
859 metrics.IsFecCodewordsCorrected = &extension.GetOnuCountersResponse_FecCodewordsCorrected{
860 FecCodewordsCorrected: uint64(stats[FecCodewordsCorrected]),
861 }
862 metrics.IsFecCodewordsUncorrectable = &extension.GetOnuCountersResponse_FecCodewordsUncorrectable{
863 FecCodewordsUncorrectable: uint64(stats[fecCodewordsUncorrectable]),
864 }
865 metrics.IsFecCodewords = &extension.GetOnuCountersResponse_FecCodewords{
866 FecCodewords: uint64(stats[FecCodewords]),
867 }
868 metrics.IsFecCorrectedUnits = &extension.GetOnuCountersResponse_FecCorrectedUnits{
869 FecCorrectedUnits: uint64(stats[FecCorrectedUnits]),
870 }
871 metrics.IsXgemKeyErrors = &extension.GetOnuCountersResponse_XgemKeyErrors{
872 XgemKeyErrors: uint64(stats[XGEMKeyErrors]),
873 }
874 metrics.IsXgemLoss = &extension.GetOnuCountersResponse_XgemLoss{
875 XgemLoss: uint64(stats[XGEMLoss]),
876 }
877 metrics.IsRxPloamsError = &extension.GetOnuCountersResponse_RxPloamsError{
878 RxPloamsError: uint64(stats[RxPloamsError]),
879 }
880 metrics.IsRxPloamsNonIdle = &extension.GetOnuCountersResponse_RxPloamsNonIdle{
881 RxPloamsNonIdle: uint64(stats[RxPloamsNonIdle]),
882 }
883 metrics.IsRxOmci = &extension.GetOnuCountersResponse_RxOmci{
884 RxOmci: uint64(stats[RxOmci]),
885 }
886 metrics.IsRxOmciPacketsCrcError = &extension.GetOnuCountersResponse_RxOmciPacketsCrcError{
887 RxOmciPacketsCrcError: uint64(stats[RxOmciPacketsCrcError]),
888 }
889 metrics.IsRxBytes = &extension.GetOnuCountersResponse_RxBytes{
890 RxBytes: uint64(stats[RxBytes]),
891 }
892 metrics.IsRxPackets = &extension.GetOnuCountersResponse_RxPackets{
893 RxPackets: uint64(stats[RxPackets]),
894 }
895 metrics.IsTxBytes = &extension.GetOnuCountersResponse_TxBytes{
896 TxBytes: uint64(stats[TxBytes]),
897 }
898 metrics.IsTxPackets = &extension.GetOnuCountersResponse_TxPackets{
899 TxPackets: uint64(stats[TxPackets]),
900 }
901 metrics.IsBerReported = &extension.GetOnuCountersResponse_BerReported{
902 BerReported: uint64(stats[BerReported]),
903 }
904 metrics.IsLcdgErrors = &extension.GetOnuCountersResponse_LcdgErrors{
905 LcdgErrors: uint64(stats[LcdgErrors]),
906 }
907 metrics.IsRdiErrors = &extension.GetOnuCountersResponse_RdiErrors{
908 RdiErrors: uint64(stats[RdiErrors]),
909 }
910 metrics.IsTimestamp = &extension.GetOnuCountersResponse_Timestamp{
911 Timestamp: uint32(stats[Timestamp]),
912 }
913
914 singleValResp.Response.Status = extension.GetValueResponse_OK
915 logger.Debugw(ctx, "updateGetOnuPonCountersResponse", log.Fields{"resp": singleValResp})
916}
Akash Reddy Kankanalaae740fa2026-01-29 12:30:36 +0000917
918func selectCounter(primary, secondary uint64) uint64 {
919 if isValidCounter(primary) {
920 return primary
921 }
922 if isValidCounter(secondary) {
923 return secondary
924 }
925 return 0
926}
927
928func isValidCounter(metric uint64) bool {
929 return metric != 0 && metric != math.MaxUint64
930}