blob: 778accc3807263e179f5fc1e69c93d88fd8e4b94 [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
17//Package adaptercore provides the utility for olt devices, flows and statistics
Abhilash S.L765ad002019-04-24 16:40:57 +053018package adaptercore
19
20import (
21 "errors"
22 "fmt"
23
Scott Baker51290152019-10-24 14:23:20 -070024 "github.com/opencord/voltha-lib-go/v2/pkg/log"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070025 "github.com/opencord/voltha-protos/go/openolt"
Abhilash S.L765ad002019-04-24 16:40:57 +053026 "github.com/opencord/voltha-protos/go/voltha"
27)
28
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070029// PonPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +053030type PonPort struct {
31 /*
32 This is a highly reduced version taken from the adtran pon_port.
33 TODO: Extend for use in the openolt adapter set.
34 */
35 /* MAX_ONUS_SUPPORTED = 256
36 DEFAULT_ENABLED = False
37 MAX_DEPLOYMENT_RANGE = 25000 # Meters (OLT-PB maximum)
38
39 _MCAST_ONU_ID = 253
40 _MCAST_ALLOC_BASE = 0x500
41
42 _SUPPORTED_ACTIVATION_METHODS = ['autodiscovery'] # , 'autoactivate']
43 _SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
44 */
45 PONID uint32
46 DeviceID string
47 IntfID uint32
48 PortNum uint32
49 PortID uint32
50 Label string
51 ONUs map[uint32]interface{}
52 ONUsByID map[uint32]interface{}
53
54 RxBytes uint64
55 RxPackets uint64
56 RxMcastPackets uint64
57 RxBcastPackets uint64
58 RxErrorPackets uint64
59 TxBytes uint64
60 TxPackets uint64
61 TxUcastPackets uint64
62 TxMcastPackets uint64
63 TxBcastPackets uint64
64 TxErrorPackets uint64
65}
66
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067// NewPONPort returns a new instance of PonPort initialized with given PONID, DeviceID, IntfID and PortNum
Abhilash S.L765ad002019-04-24 16:40:57 +053068func NewPONPort(PONID uint32, DeviceID string, IntfID uint32, PortNum uint32) *PonPort {
69
70 var PON PonPort
71
72 PON.PONID = PONID
73 PON.DeviceID = DeviceID
74 PON.IntfID = IntfID
75 PON.PortNum = PortNum
76 PON.PortID = 0
77 PON.Label = fmt.Sprintf("%s,%d", "pon-", PONID)
78
79 PON.ONUs = make(map[uint32]interface{})
80 PON.ONUsByID = make(map[uint32]interface{})
81
82 /*
83 Statistics taken from nni_port
84 self.intf_id = 0 #handled by getter
85 self.port_no = 0 #handled by getter
86 self.port_id = 0 #handled by getter
87
88 Note: In the current implementation of the kpis coming from the BAL the stats are the
89 samne model for NNI and PON.
90
91 TODO: Integrate additional kpis for the PON and other southbound port objecgts.
92
93 */
94
95 PON.RxBytes = 0
96 PON.RxPackets = 0
97 PON.RxMcastPackets = 0
98 PON.RxBcastPackets = 0
99 PON.RxErrorPackets = 0
100 PON.TxBytes = 0
101 PON.TxPackets = 0
102 PON.TxUcastPackets = 0
103 PON.TxMcastPackets = 0
104 PON.TxBcastPackets = 0
105 PON.TxErrorPackets = 0
106
107 /* def __str__(self):
108 return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
109 self._admin_state,
110 self._oper_status,
111 self.olt)
112 */
113 return &PON
114}
115
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700116// NniPort representation
Abhilash S.L765ad002019-04-24 16:40:57 +0530117type NniPort struct {
118 /*
119 Northbound network port, often Ethernet-based
120
121 This is a highly reduced version taken from the adtran nni_port code set
122 TODO: add functions to allow for port specific values and operations
123 */
124 PortNum uint32
125 Name string
126 LogicalPort uint32
127 IntfID uint32
128
129 RxBytes uint64
130 RxPackets uint64
131 RxMcastPackets uint64
132 RxBcastPackets uint64
133 RxErrorPackets uint64
134 TxBytes uint64
135 TxPackets uint64
136 TxUcastPackets uint64
137 TxMcastPackets uint64
138 TxBcastPackets uint64
139 TxErrorPackets uint64
140}
141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142// NewNniPort returns a new instance of NniPort initialized with the given PortNum and IntfID
Abhilash S.L765ad002019-04-24 16:40:57 +0530143func NewNniPort(PortNum uint32, IntfID uint32) *NniPort {
144
145 var NNI NniPort
146
147 NNI.PortNum = PortNum
148 NNI.Name = fmt.Sprintf("%s,%d", "nni-", PortNum)
149 NNI.IntfID = IntfID
150
151 NNI.RxBytes = 0
152 NNI.RxPackets = 0
153 NNI.RxMcastPackets = 0
154 NNI.RxBcastPackets = 0
155 NNI.RxErrorPackets = 0
156 NNI.TxBytes = 0
157 NNI.TxPackets = 0
158 NNI.TxUcastPackets = 0
159 NNI.TxMcastPackets = 0
160 NNI.TxBcastPackets = 0
161 NNI.TxErrorPackets = 0
162
163 return &NNI
164}
165
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166// OpenOltStatisticsMgr structure
Abhilash S.L765ad002019-04-24 16:40:57 +0530167type OpenOltStatisticsMgr struct {
168 Device *DeviceHandler
169 NorthBoundPort map[uint32]NniPort
170 SouthBoundPort map[uint32]PonPort
171 // TODO PMMetrics Metrics
172}
173
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700174// NewOpenOltStatsMgr returns a new instance of the OpenOltStatisticsMgr
Abhilash S.L765ad002019-04-24 16:40:57 +0530175func NewOpenOltStatsMgr(Dev *DeviceHandler) *OpenOltStatisticsMgr {
176
177 var StatMgr OpenOltStatisticsMgr
178
179 StatMgr.Device = Dev
180 // TODO call metric PMMetric =
181 // Northbound and Southbound ports
182 // added to initialize the pm_metrics
183 var Ports interface{}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184 Ports, _ = InitPorts("nni", Dev.deviceID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530185 StatMgr.NorthBoundPort, _ = Ports.(map[uint32]NniPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700186 Ports, _ = InitPorts("pon", Dev.deviceID)
Abhilash S.L765ad002019-04-24 16:40:57 +0530187 StatMgr.SouthBoundPort, _ = Ports.(map[uint32]PonPort)
188
189 return &StatMgr
190}
191
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700192// InitPorts collects the port objects: nni and pon that are updated with the current data from the OLT
Abhilash S.L765ad002019-04-24 16:40:57 +0530193func InitPorts(Intftype string, DeviceID string) (interface{}, error) {
194 /*
195 This method collects the port objects: nni and pon that are updated with the
196 current data from the OLT
197
198 Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
199 and NOT the port number. When the port object is instantiated it will contain the intf_id and
200 port_no values
201
202 :param type:
203 :return:
204 */
205 var i uint32
206 if Intftype == "nni" {
207 NniPorts := make(map[uint32]NniPort)
208 for i = 0; i <= 1; i++ {
kdarapu768708d2019-09-16 23:19:15 +0530209 Port := BuildPortObject(i, "nni", DeviceID).(*NniPort)
210 NniPorts[Port.IntfID] = *Port
Abhilash S.L765ad002019-04-24 16:40:57 +0530211 }
212 return NniPorts, nil
213 } else if Intftype == "pon" {
214 PONPorts := make(map[uint32]PonPort)
215 for i = 0; i <= 16; i++ {
kdarapu768708d2019-09-16 23:19:15 +0530216 PONPort := BuildPortObject(i, "pon", DeviceID).(*PonPort)
217 PONPorts[PONPort.IntfID] = *PONPort
Abhilash S.L765ad002019-04-24 16:40:57 +0530218 }
219 return PONPorts, nil
220 } else {
221 log.Errorf("Invalid type of interface %s", Intftype)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700222 return nil, errors.New("invalid type of interface ")
Abhilash S.L765ad002019-04-24 16:40:57 +0530223 }
224}
225
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700226// BuildPortObject allows for updating north and southbound ports, newly discovered ports, and devices
Abhilash S.L765ad002019-04-24 16:40:57 +0530227func BuildPortObject(PortNum uint32, IntfType string, DeviceID string) interface{} {
228 /*
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229 Separate method to allow for updating north and southbound ports
Abhilash S.L765ad002019-04-24 16:40:57 +0530230 newly discovered ports and devices
231
232 :param port_num:
233 :param type:
234 :return:
235 */
236
237 //This builds a port object which is added to the
238 //appropriate northbound or southbound values
239 if IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700240 IntfID := IntfIDToPortNo(PortNum, voltha.Port_ETHERNET_UNI)
Abhilash S.L765ad002019-04-24 16:40:57 +0530241 return NewNniPort(PortNum, IntfID)
242 } else if IntfType == "pon" {
243 // PON ports require a different configuration
244 // intf_id and pon_id are currently equal.
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245 IntfID := IntfIDToPortNo(PortNum, voltha.Port_ETHERNET_NNI)
Abhilash S.L765ad002019-04-24 16:40:57 +0530246 PONID := IntfID
247 return NewPONPort(PONID, DeviceID, IntfID, PortNum)
248 } else {
249 log.Errorf("Invalid type of interface %s", IntfType)
250 return nil
251 }
252}
253
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700254// PortStatisticsIndication handles the port statistics indication
Abhilash S.L765ad002019-04-24 16:40:57 +0530255func (StatMgr *OpenOltStatisticsMgr) PortStatisticsIndication(PortStats *openolt.PortStatistics) {
256 log.Debugf("port-stats-collected %v", PortStats)
257 StatMgr.PortsStatisticsKpis(PortStats)
258 // TODO send stats to core topic to the voltha kafka or a different kafka ?
259}
260
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700261// FlowStatisticsIndication to be implemented
Abhilash S.L765ad002019-04-24 16:40:57 +0530262func FlowStatisticsIndication(self, FlowStats *openolt.FlowStatistics) {
263 log.Debugf("flow-stats-collected %v", FlowStats)
264 //TODO send to kafka ?
265}
266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267// PortsStatisticsKpis map the port stats values into a dictionary, creates the kpiEvent and then publish to Kafka
Abhilash S.L765ad002019-04-24 16:40:57 +0530268func (StatMgr *OpenOltStatisticsMgr) PortsStatisticsKpis(PortStats *openolt.PortStatistics) {
269
270 /*map the port stats values into a dictionary
271 Create a kpoEvent and publish to Kafka
272
273 :param port_stats:
274 :return:
275 */
276 //var err error
277 IntfID := PortStats.IntfId
278
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700279 if (IntfIDToPortNo(0, voltha.Port_ETHERNET_NNI) < IntfID) &&
280 (IntfID < IntfIDToPortNo(4, voltha.Port_ETHERNET_NNI)) {
Abhilash S.L765ad002019-04-24 16:40:57 +0530281 /*
282 for this release we are only interested in the first NNI for
283 Northbound.
284 we are not using the other 3
285 */
286 return
Abhilash S.L765ad002019-04-24 16:40:57 +0530287 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700288 PMData := make(map[string]uint64)
289 PMData["rx_bytes"] = PortStats.RxBytes
290 PMData["rx_packets"] = PortStats.RxPackets
291 PMData["rx_ucast_packets"] = PortStats.RxUcastPackets
292 PMData["rx_mcast_packets"] = PortStats.RxMcastPackets
293 PMData["rx_bcast_packets"] = PortStats.RxBcastPackets
294 PMData["rx_error_packets"] = PortStats.RxErrorPackets
295 PMData["tx_bytes"] = PortStats.TxBytes
296 PMData["tx_packets"] = PortStats.TxPackets
297 PMData["tx_ucast_packets"] = PortStats.TxUcastPackets
298 PMData["tx_mcast_packets"] = PortStats.TxMcastPackets
299 PMData["tx_bcast_packets"] = PortStats.TxBcastPackets
300 PMData["tx_error_packets"] = PortStats.TxErrorPackets
301 PMData["rx_crc_errors"] = PortStats.RxCrcErrors
302 PMData["bip_errors"] = PortStats.BipErrors
303
304 PMData["intf_id"] = uint64(PortStats.IntfId)
305
306 /*
307 Based upon the intf_id map to an nni port or a pon port
308 the intf_id is the key to the north or south bound collections
309
310 Based upon the intf_id the port object (nni_port or pon_port) will
311 have its data attr. updated by the current dataset collected.
312
313 For prefixing the rule is currently to use the port number and not the intf_id
314 */
315 //FIXME : Just use first NNI for now
316 /* TODO should the data be marshaled before sending it ?
317 if IntfID == IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) {
318 //NNI port (just the first one)
319 err = UpdatePortObjectKpiData(StatMgr.NorthBoundPorts[PortStats.IntfID], PMData)
320 } else {
321 //PON ports
322 err = UpdatePortObjectKpiData(SouthboundPorts[PortStats.IntfID], PMData)
323 }
324 if (err != nil) {
325 log.Error("Error publishing statistics data")
326 }
327 */
328
Abhilash S.L765ad002019-04-24 16:40:57 +0530329}