blob: 1b52e7c0b9b07d0c82e24aa82a6c8a2c7ed6fad9 [file] [log] [blame]
Abhilash S.L765ad002019-04-24 16:40:57 +05301/*
2 * Copyright 2019-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Abhilash S.L765ad002019-04-24 16:40:57 +053019
20import (
Neha Sharma96b7bf22020-06-15 10:37:32 +000021 "context"
Abhilash S.L765ad002019-04-24 16:40:57 +053022 "fmt"
Gamze Abakafcbd6e72020-12-17 13:25:16 +000023 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Shrey Baid26912972020-04-16 21:02:31 +053024 "sync"
25 "time"
26
Girish Gowdraa09aeab2020-09-14 16:30:52 -070027 "github.com/opencord/voltha-lib-go/v4/pkg/log"
Thomas Lee S94109f12020-03-03 16:39:29 +053028 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-protos/v4/go/openolt"
30 "github.com/opencord/voltha-protos/v4/go/voltha"
Abhilash S.L765ad002019-04-24 16:40:57 +053031)
32
Gamze Abakafcbd6e72020-12-17 13:25:16 +000033const (
34 //NNIStats statType constant
35 NNIStats = "NNIStats"
36 //PONStats statType constant
37 PONStats = "PONStats"
38 //ONUStats statType constant
39 ONUStats = "ONUStats"
40 //GEMStats statType constant
41 GEMStats = "GEMStats"
42
43 //RxBytes constant
44 RxBytes = "RxBytes"
45 //RxPackets constant
46 RxPackets = "RxPackets"
47 //TxBytes constant
48 TxBytes = "TxBytes"
49 //TxPackets constant
50 TxPackets = "TxPackets"
51 //FecCodewords constant
52 FecCodewords = "FecCodewords"
53 //BipUnits constant
54 BipUnits = "BipUnits"
55 //BipErrors constant
56 BipErrors = "BipErrors"
57 //RxPloamsNonIdle constant
58 RxPloamsNonIdle = "RxPloamsNonIdle"
59 //RxPloamsError constant
60 RxPloamsError = "RxPloamsError"
61 //RxOmci constant
62 RxOmci = "RxOmci"
63 //RxOmciPacketsCrcError constant
64 RxOmciPacketsCrcError = "RxOmciPacketsCrcError"
65 //PositiveDrift constant
66 PositiveDrift = "PositiveDrift"
67 //NegativeDrift constant
68 NegativeDrift = "NegativeDrift"
69 //DelimiterMissDetection constant
70 DelimiterMissDetection = "DelimiterMissDetection"
71 //FecCorrectedSymbols constant
72 FecCorrectedSymbols = "FecCorrectedSymbols"
73 //FecCodewordsCorrected constant
74 FecCodewordsCorrected = "FecCodewordsCorrected"
75 //fecCodewordsUncorrectable constant
76 fecCodewordsUncorrectable = "fec_codewords_uncorrectable"
77 //FecCorrectedUnits constant
78 FecCorrectedUnits = "FecCorrectedUnits"
79 //XGEMKeyErrors constant
80 XGEMKeyErrors = "XGEMKeyErrors"
81 //XGEMLoss constant
82 XGEMLoss = "XGEMLOSS"
83 //BerReported constant
84 BerReported = "BerReported"
85 //LcdgErrors constant
86 LcdgErrors = "LcdgErrors"
87 //RdiErrors constant
88 RdiErrors = "RdiErrors"
89)
90
Naga Manjunath7615e552019-10-11 22:35:47 +053091var mutex = &sync.Mutex{}
92
Gamze Abakafcbd6e72020-12-17 13:25:16 +000093var onuStats = make(chan *openolt.OnuStatistics, 100)
94var gemStats = make(chan *openolt.GemPortStatistics, 100)
95
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096// PonPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +053097type PonPort struct {
98 /*
99 This is a highly reduced version taken from the adtran pon_port.
100 TODO: Extend for use in the openolt adapter set.
101 */
102 /* MAX_ONUS_SUPPORTED = 256
103 DEFAULT_ENABLED = False
104 MAX_DEPLOYMENT_RANGE = 25000 # Meters (OLT-PB maximum)
105
106 _MCAST_ONU_ID = 253
107 _MCAST_ALLOC_BASE = 0x500
108
109 _SUPPORTED_ACTIVATION_METHODS = ['autodiscovery'] # , 'autoactivate']
110 _SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
111 */
112 PONID uint32
113 DeviceID string
114 IntfID uint32
115 PortNum uint32
116 PortID uint32
117 Label string
118 ONUs map[uint32]interface{}
119 ONUsByID map[uint32]interface{}
120
121 RxBytes uint64
122 RxPackets uint64
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000123 RxUcastPackets uint64
Abhilash S.L765ad002019-04-24 16:40:57 +0530124 RxMcastPackets uint64
125 RxBcastPackets uint64
126 RxErrorPackets uint64
127 TxBytes uint64
128 TxPackets uint64
129 TxUcastPackets uint64
130 TxMcastPackets uint64
131 TxBcastPackets uint64
132 TxErrorPackets uint64
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000133 RxCrcErrors uint64
134 BipErrors uint64
Abhilash S.L765ad002019-04-24 16:40:57 +0530135}
136
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137// NewPONPort returns a new instance of PonPort initialized with given PONID, DeviceID, IntfID and PortNum
Abhilash S.L765ad002019-04-24 16:40:57 +0530138func NewPONPort(PONID uint32, DeviceID string, IntfID uint32, PortNum uint32) *PonPort {
139
140 var PON PonPort
141
142 PON.PONID = PONID
143 PON.DeviceID = DeviceID
144 PON.IntfID = IntfID
145 PON.PortNum = PortNum
146 PON.PortID = 0
Naga Manjunath7615e552019-10-11 22:35:47 +0530147 PON.Label = fmt.Sprintf("%s%d", "pon-", PONID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530148
149 PON.ONUs = make(map[uint32]interface{})
150 PON.ONUsByID = make(map[uint32]interface{})
151
152 /*
153 Statistics taken from nni_port
154 self.intf_id = 0 #handled by getter
155 self.port_no = 0 #handled by getter
156 self.port_id = 0 #handled by getter
157
158 Note: In the current implementation of the kpis coming from the BAL the stats are the
159 samne model for NNI and PON.
160
161 TODO: Integrate additional kpis for the PON and other southbound port objecgts.
162
163 */
164
165 PON.RxBytes = 0
166 PON.RxPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000167 PON.RxUcastPackets = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530168 PON.RxMcastPackets = 0
169 PON.RxBcastPackets = 0
170 PON.RxErrorPackets = 0
171 PON.TxBytes = 0
172 PON.TxPackets = 0
173 PON.TxUcastPackets = 0
174 PON.TxMcastPackets = 0
175 PON.TxBcastPackets = 0
176 PON.TxErrorPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000177 PON.RxCrcErrors = 0
178 PON.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530179
180 /* def __str__(self):
181 return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
182 self._admin_state,
183 self._oper_status,
184 self.olt)
185 */
186 return &PON
187}
188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189// NniPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530190type NniPort struct {
191 /*
192 Northbound network port, often Ethernet-based
193
194 This is a highly reduced version taken from the adtran nni_port code set
195 TODO: add functions to allow for port specific values and operations
196 */
197 PortNum uint32
198 Name string
199 LogicalPort uint32
200 IntfID uint32
201
202 RxBytes uint64
203 RxPackets uint64
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000204 RxUcastPackets uint64
Abhilash S.L765ad002019-04-24 16:40:57 +0530205 RxMcastPackets uint64
206 RxBcastPackets uint64
207 RxErrorPackets uint64
208 TxBytes uint64
209 TxPackets uint64
210 TxUcastPackets uint64
211 TxMcastPackets uint64
212 TxBcastPackets uint64
213 TxErrorPackets uint64
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000214 RxCrcErrors uint64
215 BipErrors uint64
Abhilash S.L765ad002019-04-24 16:40:57 +0530216}
217
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700218// NewNniPort returns a new instance of NniPort initialized with the given PortNum and IntfID
Abhilash S.L765ad002019-04-24 16:40:57 +0530219func NewNniPort(PortNum uint32, IntfID uint32) *NniPort {
220
221 var NNI NniPort
222
223 NNI.PortNum = PortNum
Naga Manjunath7615e552019-10-11 22:35:47 +0530224 NNI.Name = fmt.Sprintf("%s%d", "nni-", PortNum)
Abhilash S.L765ad002019-04-24 16:40:57 +0530225 NNI.IntfID = IntfID
226
227 NNI.RxBytes = 0
228 NNI.RxPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000229 NNI.RxUcastPackets = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530230 NNI.RxMcastPackets = 0
231 NNI.RxBcastPackets = 0
232 NNI.RxErrorPackets = 0
233 NNI.TxBytes = 0
234 NNI.TxPackets = 0
235 NNI.TxUcastPackets = 0
236 NNI.TxMcastPackets = 0
237 NNI.TxBcastPackets = 0
238 NNI.TxErrorPackets = 0
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000239 NNI.RxCrcErrors = 0
240 NNI.BipErrors = 0
Abhilash S.L765ad002019-04-24 16:40:57 +0530241
242 return &NNI
243}
244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245// OpenOltStatisticsMgr structure
Abhilash S.L765ad002019-04-24 16:40:57 +0530246type OpenOltStatisticsMgr struct {
247 Device *DeviceHandler
Naga Manjunath7615e552019-10-11 22:35:47 +0530248 NorthBoundPort map[uint32]*NniPort
249 SouthBoundPort map[uint32]*PonPort
Abhilash S.L765ad002019-04-24 16:40:57 +0530250 // TODO PMMetrics Metrics
251}
252
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700253// NewOpenOltStatsMgr returns a new instance of the OpenOltStatisticsMgr
Neha Sharma96b7bf22020-06-15 10:37:32 +0000254func NewOpenOltStatsMgr(ctx context.Context, Dev *DeviceHandler) *OpenOltStatisticsMgr {
Abhilash S.L765ad002019-04-24 16:40:57 +0530255
256 var StatMgr OpenOltStatisticsMgr
257
258 StatMgr.Device = Dev
259 // TODO call metric PMMetric =
260 // Northbound and Southbound ports
261 // added to initialize the pm_metrics
262 var Ports interface{}
Neha Sharma96b7bf22020-06-15 10:37:32 +0000263 Ports, _ = InitPorts(ctx, "nni", Dev.device.Id, 1)
Naga Manjunath7615e552019-10-11 22:35:47 +0530264 StatMgr.NorthBoundPort, _ = Ports.(map[uint32]*NniPort)
265 NumPonPorts := Dev.resourceMgr.DevInfo.GetPonPorts()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000266 Ports, _ = InitPorts(ctx, "pon", Dev.device.Id, NumPonPorts)
Naga Manjunath7615e552019-10-11 22:35:47 +0530267 StatMgr.SouthBoundPort, _ = Ports.(map[uint32]*PonPort)
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000268 if StatMgr.Device.openOLT.enableONUStats {
269 go StatMgr.publishOnuStats()
270 }
271 if StatMgr.Device.openOLT.enableGemStats {
272 go StatMgr.publishGemStats()
273 }
Abhilash S.L765ad002019-04-24 16:40:57 +0530274 return &StatMgr
275}
276
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700277// 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 +0000278func InitPorts(ctx context.Context, Intftype string, DeviceID string, numOfPorts uint32) (interface{}, error) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530279 /*
280 This method collects the port objects: nni and pon that are updated with the
281 current data from the OLT
282
283 Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
284 and NOT the port number. When the port object is instantiated it will contain the intf_id and
285 port_no values
286
287 :param type:
288 :return:
289 */
290 var i uint32
291 if Intftype == "nni" {
Naga Manjunath7615e552019-10-11 22:35:47 +0530292 NniPorts := make(map[uint32]*NniPort)
293 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000294 Port := BuildPortObject(ctx, i, "nni", DeviceID).(*NniPort)
Naga Manjunath7615e552019-10-11 22:35:47 +0530295 NniPorts[Port.IntfID] = Port
Abhilash S.L765ad002019-04-24 16:40:57 +0530296 }
297 return NniPorts, nil
298 } else if Intftype == "pon" {
Naga Manjunath7615e552019-10-11 22:35:47 +0530299 PONPorts := make(map[uint32]*PonPort)
300 for i = 0; i < numOfPorts; i++ {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000301 PONPort := BuildPortObject(ctx, i, "pon", DeviceID).(*PonPort)
Naga Manjunath7615e552019-10-11 22:35:47 +0530302 PONPorts[PortNoToIntfID(PONPort.IntfID, voltha.Port_PON_OLT)] = PONPort
Abhilash S.L765ad002019-04-24 16:40:57 +0530303 }
304 return PONPorts, nil
305 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000306 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"interface-type": Intftype})
Thomas Lee S94109f12020-03-03 16:39:29 +0530307 return nil, olterrors.NewErrInvalidValue(log.Fields{"interface-type": Intftype}, nil)
Abhilash S.L765ad002019-04-24 16:40:57 +0530308 }
309}
310
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700311// BuildPortObject allows for updating north and southbound ports, newly discovered ports, and devices
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312func BuildPortObject(ctx context.Context, PortNum uint32, IntfType string, DeviceID string) interface{} {
Abhilash S.L765ad002019-04-24 16:40:57 +0530313 /*
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700314 Separate method to allow for updating north and southbound ports
Abhilash S.L765ad002019-04-24 16:40:57 +0530315 newly discovered ports and devices
316
317 :param port_num:
318 :param type:
319 :return:
320 */
321
322 //This builds a port object which is added to the
323 //appropriate northbound or southbound values
324 if IntfType == "nni" {
Naga Manjunath7615e552019-10-11 22:35:47 +0530325 IntfID := IntfIDToPortNo(PortNum, voltha.Port_ETHERNET_NNI)
326 nniID := PortNoToIntfID(IntfID, voltha.Port_ETHERNET_NNI)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000327 logger.Debugw(ctx, "interface-type-nni",
Shrey Baid26912972020-04-16 21:02:31 +0530328 log.Fields{
329 "nni-id": nniID,
330 "intf-type": IntfType})
Naga Manjunath7615e552019-10-11 22:35:47 +0530331 return NewNniPort(PortNum, nniID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530332 } else if IntfType == "pon" {
333 // PON ports require a different configuration
334 // intf_id and pon_id are currently equal.
Naga Manjunath7615e552019-10-11 22:35:47 +0530335 IntfID := IntfIDToPortNo(PortNum, voltha.Port_PON_OLT)
336 PONID := PortNoToIntfID(IntfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000337 logger.Debugw(ctx, "interface-type-pon",
Shrey Baid26912972020-04-16 21:02:31 +0530338 log.Fields{
339 "pon-id": PONID,
340 "intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530341 return NewPONPort(PONID, DeviceID, IntfID, PortNum)
342 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000343 logger.Errorw(ctx, "invalid-type-of-interface", log.Fields{"intf-type": IntfType})
Abhilash S.L765ad002019-04-24 16:40:57 +0530344 return nil
345 }
346}
347
Naga Manjunath7615e552019-10-11 22:35:47 +0530348// collectNNIMetrics will collect the nni port metrics
349func (StatMgr *OpenOltStatisticsMgr) collectNNIMetrics(nniID uint32) map[string]float32 {
350
351 nnival := make(map[string]float32)
352 mutex.Lock()
353 cm := StatMgr.Device.portStats.NorthBoundPort[nniID]
354 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000355 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530356
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000357 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400358 for metric := range metricNames {
359 if metricNames[metric].Enabled {
360 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530361 }
362 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000363
364 for _, mName := range metrics {
365 switch mName {
366 case "rx_bytes":
367 nnival["RxBytes"] = float32(cm.RxBytes)
368 case "rx_packets":
369 nnival["RxPackets"] = float32(cm.RxPackets)
370 case "rx_ucast_packets":
371 nnival["RxUcastPackets"] = float32(cm.RxUcastPackets)
372 case "rx_mcast_packets":
373 nnival["RxMcastPackets"] = float32(cm.RxMcastPackets)
374 case "rx_bcast_packets":
375 nnival["RxBcastPackets"] = float32(cm.RxBcastPackets)
376 case "tx_bytes":
377 nnival["TxBytes"] = float32(cm.TxBytes)
378 case "tx_packets":
379 nnival["TxPackets"] = float32(cm.TxPackets)
380 case "tx_mcast_packets":
381 nnival["TxMcastPackets"] = float32(cm.TxMcastPackets)
382 case "tx_bcast_packets":
383 nnival["TxBcastPackets"] = float32(cm.TxBcastPackets)
384 }
385 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530386 return nnival
387}
388
389// collectPONMetrics will collect the pon port metrics
390func (StatMgr *OpenOltStatisticsMgr) collectPONMetrics(pID uint32) map[string]float32 {
391
392 ponval := make(map[string]float32)
393 mutex.Lock()
394 cm := StatMgr.Device.portStats.SouthBoundPort[pID]
395 mutex.Unlock()
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000396 metricNames := StatMgr.Device.metrics.GetSubscriberMetrics()
Naga Manjunath7615e552019-10-11 22:35:47 +0530397
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000398 var metrics []string
Kent Hagermane6ff1012020-07-14 15:07:53 -0400399 for metric := range metricNames {
400 if metricNames[metric].Enabled {
401 metrics = append(metrics, metric)
Naga Manjunath7615e552019-10-11 22:35:47 +0530402 }
403 }
Rohan Agrawalda5e0b22020-05-20 11:10:26 +0000404
405 for _, mName := range metrics {
406 switch mName {
407 case "rx_bytes":
408 ponval["RxBytes"] = float32(cm.RxBytes)
409 case "rx_packets":
410 ponval["RxPackets"] = float32(cm.RxPackets)
411 case "rx_ucast_packets":
412 ponval["RxUcastPackets"] = float32(cm.RxUcastPackets)
413 case "rx_mcast_packets":
414 ponval["RxMcastPackets"] = float32(cm.RxMcastPackets)
415 case "rx_bcast_packets":
416 ponval["RxBcastPackets"] = float32(cm.RxBcastPackets)
417 case "tx_bytes":
418 ponval["TxBytes"] = float32(cm.TxBytes)
419 case "tx_packets":
420 ponval["TxPackets"] = float32(cm.TxPackets)
421 case "tx_mcast_packets":
422 ponval["TxMcastPackets"] = float32(cm.TxMcastPackets)
423 case "tx_bcast_packets":
424 ponval["TxBcastPackets"] = float32(cm.TxBcastPackets)
425 }
426 }
427
Naga Manjunath7615e552019-10-11 22:35:47 +0530428 return ponval
429}
430
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000431// converGemStats will convert gem stats response to kpi context
432func (StatMgr *OpenOltStatisticsMgr) convertGemStats(gemStats *openolt.GemPortStatistics) map[string]float32 {
433 gemStatsVal := make(map[string]float32)
434 gemStatsVal[IntfID] = float32(gemStats.IntfId)
435 gemStatsVal[GemID] = float32(gemStats.GemportId)
436 gemStatsVal[RxPackets] = float32(gemStats.RxPackets)
437 gemStatsVal[RxBytes] = float32(gemStats.RxBytes)
438 gemStatsVal[TxPackets] = float32(gemStats.TxPackets)
439 gemStatsVal[TxBytes] = float32(gemStats.TxBytes)
440 return gemStatsVal
441}
442
443// convertONUStats will convert onu stats response to kpi context
444func (StatMgr *OpenOltStatisticsMgr) convertONUStats(onuStats *openolt.OnuStatistics) map[string]float32 {
445 onuStatsVal := make(map[string]float32)
446 onuStatsVal[IntfID] = float32(onuStats.IntfId)
447 onuStatsVal[OnuID] = float32(onuStats.OnuId)
448 onuStatsVal[PositiveDrift] = float32(onuStats.PositiveDrift)
449 onuStatsVal[NegativeDrift] = float32(onuStats.NegativeDrift)
450 onuStatsVal[DelimiterMissDetection] = float32(onuStats.DelimiterMissDetection)
451 onuStatsVal[BipErrors] = float32(onuStats.BipErrors)
452 onuStatsVal[BipUnits] = float32(onuStats.BipUnits)
453 onuStatsVal[FecCorrectedSymbols] = float32(onuStats.FecCorrectedSymbols)
454 onuStatsVal[FecCodewordsCorrected] = float32(onuStats.FecCodewordsCorrected)
455 onuStatsVal[fecCodewordsUncorrectable] = float32(onuStats.FecCodewordsUncorrectable)
456 onuStatsVal[FecCodewords] = float32(onuStats.FecCodewords)
457 onuStatsVal[FecCorrectedUnits] = float32(onuStats.FecCorrectedUnits)
458 onuStatsVal[XGEMKeyErrors] = float32(onuStats.XgemKeyErrors)
459 onuStatsVal[XGEMLoss] = float32(onuStats.XgemLoss)
460 onuStatsVal[RxPloamsError] = float32(onuStats.RxPloamsError)
461 onuStatsVal[RxPloamsNonIdle] = float32(onuStats.RxPloamsNonIdle)
462 onuStatsVal[RxOmci] = float32(onuStats.RxOmci)
463 onuStatsVal[RxOmciPacketsCrcError] = float32(onuStats.RxOmciPacketsCrcError)
464 onuStatsVal[RxBytes] = float32(onuStats.RxBytes)
465 onuStatsVal[RxPackets] = float32(onuStats.RxPackets)
466 onuStatsVal[TxBytes] = float32(onuStats.TxBytes)
467 onuStatsVal[TxPackets] = float32(onuStats.TxPackets)
468 onuStatsVal[BerReported] = float32(onuStats.BerReported)
469 onuStatsVal[LcdgErrors] = float32(onuStats.LcdgErrors)
470 onuStatsVal[RdiErrors] = float32(onuStats.RdiErrors)
471 return onuStatsVal
472}
473
474// collectOnuStats will collect the onu metrics
475func (StatMgr *OpenOltStatisticsMgr) collectOnuStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
476 onu := &openolt.Onu{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID}
477 logger.Debugw(ctx, "pulling-onu-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID})
478 if stats, err := StatMgr.Device.Client.GetOnuStatistics(context.Background(), onu); err == nil {
479 onuStats <- stats
480 } else {
481 logger.Errorw(ctx, "error-while-getting-onu-stats-for-onu", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "err": err})
482 }
483}
484
485// collectOnuAndGemStats will collect both onu and gem metrics
486func (StatMgr *OpenOltStatisticsMgr) collectOnuAndGemStats(ctx context.Context, onuGemInfo []rsrcMgr.OnuGemInfo) {
487 if !StatMgr.Device.openOLT.enableONUStats && !StatMgr.Device.openOLT.enableGemStats {
488 return
489 }
490
491 for _, onuInfo := range onuGemInfo {
492 if StatMgr.Device.openOLT.enableONUStats {
493 go StatMgr.collectOnuStats(ctx, onuInfo)
494 }
495 if StatMgr.Device.openOLT.enableGemStats {
496 go StatMgr.collectGemStats(ctx, onuInfo)
497 }
498 }
499}
500
501// collectGemStats will collect gem metrics
502func (StatMgr *OpenOltStatisticsMgr) collectGemStats(ctx context.Context, onuGemInfo rsrcMgr.OnuGemInfo) {
503 for _, gem := range onuGemInfo.GemPorts {
504 logger.Debugw(ctx, "pulling-gem-stats", log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem})
505 onuPacket := &openolt.OnuPacket{IntfId: onuGemInfo.IntfID, OnuId: onuGemInfo.OnuID, GemportId: gem}
506 if stats, err := StatMgr.Device.Client.GetGemPortStatistics(context.Background(), onuPacket); err == nil {
507 gemStats <- stats
508 } else {
509 logger.Errorw(ctx, "error-while-getting-gem-stats-for-onu",
510 log.Fields{"IntfID": onuGemInfo.IntfID, "OnuID": onuGemInfo.OnuID, "GemID": gem, "err": err})
511 }
512 }
513}
514
515// publishGemStats will publish the gem metrics
516func (StatMgr *OpenOltStatisticsMgr) publishGemStats() {
517 for {
518 statValue := StatMgr.convertGemStats(<-gemStats)
519 StatMgr.publishMetrics(context.Background(), GEMStats, statValue, &voltha.Port{Label: "GEM"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
520 }
521}
522
523// publishOnuStats will publish the onu metrics
524func (StatMgr *OpenOltStatisticsMgr) publishOnuStats() {
525 for {
526 statValue := StatMgr.convertONUStats(<-onuStats)
527 StatMgr.publishMetrics(context.Background(), ONUStats, statValue, &voltha.Port{Label: "ONU"}, StatMgr.Device.device.Id, StatMgr.Device.device.Type)
528 }
529}
530
531// publishMetrics will publish the pon port metrics
532func (StatMgr OpenOltStatisticsMgr) publishMetrics(ctx context.Context, statType string, val map[string]float32,
Girish Gowdra34815db2020-05-11 17:18:04 -0700533 port *voltha.Port, devID string, devType string) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000534 logger.Debugw(ctx, "publish-metrics",
Shrey Baid26912972020-04-16 21:02:31 +0530535 log.Fields{
536 "port": port.Label,
537 "metrics": val})
Naga Manjunath7615e552019-10-11 22:35:47 +0530538
539 var metricInfo voltha.MetricInformation
540 var ke voltha.KpiEvent2
Esin Karamanccb714b2019-11-29 15:02:06 +0000541 var volthaEventSubCatgry voltha.EventSubCategory_Types
Girish Gowdra34815db2020-05-11 17:18:04 -0700542 metricsContext := make(map[string]string)
543 metricsContext["oltid"] = devID
544 metricsContext["devicetype"] = devType
545 metricsContext["portlabel"] = port.Label
Naga Manjunath7615e552019-10-11 22:35:47 +0530546
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000547 if statType == NNIStats {
Naga Manjunath7615e552019-10-11 22:35:47 +0530548 volthaEventSubCatgry = voltha.EventSubCategory_NNI
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000549 } else if statType == PONStats {
Naga Manjunath7615e552019-10-11 22:35:47 +0530550 volthaEventSubCatgry = voltha.EventSubCategory_PON
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000551 } else if statType == GEMStats || statType == ONUStats {
552 volthaEventSubCatgry = voltha.EventSubCategory_ONT
Naga Manjunath7615e552019-10-11 22:35:47 +0530553 }
554
555 raisedTs := time.Now().UnixNano()
556 mmd := voltha.MetricMetaData{
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000557 Title: statType,
Naga Manjunath7615e552019-10-11 22:35:47 +0530558 Ts: float64(raisedTs),
Girish Gowdra34815db2020-05-11 17:18:04 -0700559 Context: metricsContext,
Naga Manjunath7615e552019-10-11 22:35:47 +0530560 DeviceId: devID,
561 }
562
563 metricInfo.Metadata = &mmd
564 metricInfo.Metrics = val
565
566 ke.SliceData = []*voltha.MetricInformation{&metricInfo}
567 ke.Type = voltha.KpiEventType_slice
568 ke.Ts = float64(time.Now().UnixNano())
569
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 if err := StatMgr.Device.EventProxy.SendKpiEvent(ctx, "STATS_EVENT", &ke, voltha.EventCategory_EQUIPMENT, volthaEventSubCatgry, raisedTs); err != nil {
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000571 logger.Errorw(ctx, "failed-to-send-stats", log.Fields{"err": err})
Naga Manjunath7615e552019-10-11 22:35:47 +0530572 }
Naga Manjunath7615e552019-10-11 22:35:47 +0530573}
574
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700575// PortStatisticsIndication handles the port statistics indication
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576func (StatMgr *OpenOltStatisticsMgr) PortStatisticsIndication(ctx context.Context, PortStats *openolt.PortStatistics, NumPonPorts uint32) {
577 StatMgr.PortsStatisticsKpis(ctx, PortStats, NumPonPorts)
578 logger.Debugw(ctx, "received-port-stats-indication", log.Fields{"port-stats": PortStats})
Abhilash S.L765ad002019-04-24 16:40:57 +0530579 // TODO send stats to core topic to the voltha kafka or a different kafka ?
580}
581
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700582// FlowStatisticsIndication to be implemented
Neha Sharma96b7bf22020-06-15 10:37:32 +0000583func FlowStatisticsIndication(ctx context.Context, self, FlowStats *openolt.FlowStatistics) {
584 logger.Debugw(ctx, "flow-stats-collected", log.Fields{"flow-stats": FlowStats})
Abhilash S.L765ad002019-04-24 16:40:57 +0530585 //TODO send to kafka ?
586}
587
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700588// PortsStatisticsKpis map the port stats values into a dictionary, creates the kpiEvent and then publish to Kafka
Neha Sharma96b7bf22020-06-15 10:37:32 +0000589func (StatMgr *OpenOltStatisticsMgr) PortsStatisticsKpis(ctx context.Context, PortStats *openolt.PortStatistics, NumPonPorts uint32) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530590
591 /*map the port stats values into a dictionary
592 Create a kpoEvent and publish to Kafka
593
594 :param port_stats:
595 :return:
596 */
597 //var err error
598 IntfID := PortStats.IntfId
599
Naga Manjunath7615e552019-10-11 22:35:47 +0530600 if (IntfIDToPortNo(1, voltha.Port_ETHERNET_NNI) < IntfID) &&
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700601 (IntfID < IntfIDToPortNo(4, voltha.Port_ETHERNET_NNI)) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530602 /*
603 for this release we are only interested in the first NNI for
604 Northbound.
605 we are not using the other 3
606 */
607 return
Naga Manjunath7615e552019-10-11 22:35:47 +0530608 } else if IntfIDToPortNo(0, voltha.Port_ETHERNET_NNI) == IntfID {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700609
Naga Manjunath7615e552019-10-11 22:35:47 +0530610 var portNNIStat NniPort
611 portNNIStat.IntfID = IntfID
612 portNNIStat.PortNum = uint32(0)
613 portNNIStat.RxBytes = PortStats.RxBytes
614 portNNIStat.RxPackets = PortStats.RxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000615 portNNIStat.RxUcastPackets = PortStats.RxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530616 portNNIStat.RxMcastPackets = PortStats.RxMcastPackets
617 portNNIStat.RxBcastPackets = PortStats.RxBcastPackets
618 portNNIStat.TxBytes = PortStats.TxBytes
619 portNNIStat.TxPackets = PortStats.TxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000620 portNNIStat.TxUcastPackets = PortStats.TxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530621 portNNIStat.TxMcastPackets = PortStats.TxMcastPackets
622 portNNIStat.TxBcastPackets = PortStats.TxBcastPackets
623 mutex.Lock()
624 StatMgr.NorthBoundPort[0] = &portNNIStat
625 mutex.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 logger.Debugw(ctx, "received-nni-stats", log.Fields{"nni-stats": StatMgr.NorthBoundPort})
Naga Manjunath7615e552019-10-11 22:35:47 +0530627 }
628 for i := uint32(0); i < NumPonPorts; i++ {
629
630 if IntfIDToPortNo(i, voltha.Port_PON_OLT) == IntfID {
631 var portPonStat PonPort
632 portPonStat.IntfID = IntfID
633 portPonStat.PortNum = i
634 portPonStat.PONID = i
635 portPonStat.RxBytes = PortStats.RxBytes
636 portPonStat.RxPackets = PortStats.RxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000637 portPonStat.RxUcastPackets = PortStats.RxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530638 portPonStat.RxMcastPackets = PortStats.RxMcastPackets
639 portPonStat.RxBcastPackets = PortStats.RxBcastPackets
640 portPonStat.TxBytes = PortStats.TxBytes
641 portPonStat.TxPackets = PortStats.TxPackets
Dileep Kuchhangi52cfbe12020-01-15 20:16:21 +0000642 portPonStat.TxUcastPackets = PortStats.TxUcastPackets
Naga Manjunath7615e552019-10-11 22:35:47 +0530643 portPonStat.TxMcastPackets = PortStats.TxMcastPackets
644 portPonStat.TxBcastPackets = PortStats.TxBcastPackets
645 mutex.Lock()
646 StatMgr.SouthBoundPort[i] = &portPonStat
647 mutex.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000648 logger.Debugw(ctx, "received-pon-stats-for-port", log.Fields{"port-pon-stats": portPonStat})
Naga Manjunath7615e552019-10-11 22:35:47 +0530649 }
650 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700651
652 /*
653 Based upon the intf_id map to an nni port or a pon port
654 the intf_id is the key to the north or south bound collections
655
656 Based upon the intf_id the port object (nni_port or pon_port) will
657 have its data attr. updated by the current dataset collected.
658
659 For prefixing the rule is currently to use the port number and not the intf_id
660 */
661 //FIXME : Just use first NNI for now
662 /* TODO should the data be marshaled before sending it ?
663 if IntfID == IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) {
664 //NNI port (just the first one)
665 err = UpdatePortObjectKpiData(StatMgr.NorthBoundPorts[PortStats.IntfID], PMData)
666 } else {
667 //PON ports
668 err = UpdatePortObjectKpiData(SouthboundPorts[PortStats.IntfID], PMData)
669 }
670 if (err != nil) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 logger.Error(ctx, "Error publishing statistics data")
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700672 }
673 */
674
Abhilash S.L765ad002019-04-24 16:40:57 +0530675}