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