blob: 8d7f46782050f93e561d1bab1c0d43676826d086 [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 */
16package adaptercore
17
18import (
19 "errors"
20 "fmt"
21
22 "github.com/opencord/voltha-go/common/log"
23 openolt "github.com/opencord/voltha-protos/go/openolt"
24 "github.com/opencord/voltha-protos/go/voltha"
25)
26
27type PonPort struct {
28 /*
29 This is a highly reduced version taken from the adtran pon_port.
30 TODO: Extend for use in the openolt adapter set.
31 */
32 /* MAX_ONUS_SUPPORTED = 256
33 DEFAULT_ENABLED = False
34 MAX_DEPLOYMENT_RANGE = 25000 # Meters (OLT-PB maximum)
35
36 _MCAST_ONU_ID = 253
37 _MCAST_ALLOC_BASE = 0x500
38
39 _SUPPORTED_ACTIVATION_METHODS = ['autodiscovery'] # , 'autoactivate']
40 _SUPPORTED_AUTHENTICATION_METHODS = ['serial-number']
41 */
42 PONID uint32
43 DeviceID string
44 IntfID uint32
45 PortNum uint32
46 PortID uint32
47 Label string
48 ONUs map[uint32]interface{}
49 ONUsByID map[uint32]interface{}
50
51 RxBytes uint64
52 RxPackets uint64
53 RxMcastPackets uint64
54 RxBcastPackets uint64
55 RxErrorPackets uint64
56 TxBytes uint64
57 TxPackets uint64
58 TxUcastPackets uint64
59 TxMcastPackets uint64
60 TxBcastPackets uint64
61 TxErrorPackets uint64
62}
63
64func NewPONPort(PONID uint32, DeviceID string, IntfID uint32, PortNum uint32) *PonPort {
65
66 var PON PonPort
67
68 PON.PONID = PONID
69 PON.DeviceID = DeviceID
70 PON.IntfID = IntfID
71 PON.PortNum = PortNum
72 PON.PortID = 0
73 PON.Label = fmt.Sprintf("%s,%d", "pon-", PONID)
74
75 PON.ONUs = make(map[uint32]interface{})
76 PON.ONUsByID = make(map[uint32]interface{})
77
78 /*
79 Statistics taken from nni_port
80 self.intf_id = 0 #handled by getter
81 self.port_no = 0 #handled by getter
82 self.port_id = 0 #handled by getter
83
84 Note: In the current implementation of the kpis coming from the BAL the stats are the
85 samne model for NNI and PON.
86
87 TODO: Integrate additional kpis for the PON and other southbound port objecgts.
88
89 */
90
91 PON.RxBytes = 0
92 PON.RxPackets = 0
93 PON.RxMcastPackets = 0
94 PON.RxBcastPackets = 0
95 PON.RxErrorPackets = 0
96 PON.TxBytes = 0
97 PON.TxPackets = 0
98 PON.TxUcastPackets = 0
99 PON.TxMcastPackets = 0
100 PON.TxBcastPackets = 0
101 PON.TxErrorPackets = 0
102
103 /* def __str__(self):
104 return "PonPort-{}: Admin: {}, Oper: {}, OLT: {}".format(self._label,
105 self._admin_state,
106 self._oper_status,
107 self.olt)
108 */
109 return &PON
110}
111
112type NniPort struct {
113 /*
114 Northbound network port, often Ethernet-based
115
116 This is a highly reduced version taken from the adtran nni_port code set
117 TODO: add functions to allow for port specific values and operations
118 */
119 PortNum uint32
120 Name string
121 LogicalPort uint32
122 IntfID uint32
123
124 RxBytes uint64
125 RxPackets uint64
126 RxMcastPackets uint64
127 RxBcastPackets uint64
128 RxErrorPackets uint64
129 TxBytes uint64
130 TxPackets uint64
131 TxUcastPackets uint64
132 TxMcastPackets uint64
133 TxBcastPackets uint64
134 TxErrorPackets uint64
135}
136
137func NewNniPort(PortNum uint32, IntfID uint32) *NniPort {
138
139 var NNI NniPort
140
141 NNI.PortNum = PortNum
142 NNI.Name = fmt.Sprintf("%s,%d", "nni-", PortNum)
143 NNI.IntfID = IntfID
144
145 NNI.RxBytes = 0
146 NNI.RxPackets = 0
147 NNI.RxMcastPackets = 0
148 NNI.RxBcastPackets = 0
149 NNI.RxErrorPackets = 0
150 NNI.TxBytes = 0
151 NNI.TxPackets = 0
152 NNI.TxUcastPackets = 0
153 NNI.TxMcastPackets = 0
154 NNI.TxBcastPackets = 0
155 NNI.TxErrorPackets = 0
156
157 return &NNI
158}
159
160type OpenOltStatisticsMgr struct {
161 Device *DeviceHandler
162 NorthBoundPort map[uint32]NniPort
163 SouthBoundPort map[uint32]PonPort
164 // TODO PMMetrics Metrics
165}
166
167func NewOpenOltStatsMgr(Dev *DeviceHandler) *OpenOltStatisticsMgr {
168
169 var StatMgr OpenOltStatisticsMgr
170
171 StatMgr.Device = Dev
172 // TODO call metric PMMetric =
173 // Northbound and Southbound ports
174 // added to initialize the pm_metrics
175 var Ports interface{}
176 Ports, _ = InitPorts("nni", Dev.deviceId)
177 StatMgr.NorthBoundPort, _ = Ports.(map[uint32]NniPort)
178 Ports, _ = InitPorts("pon", Dev.deviceId)
179 StatMgr.SouthBoundPort, _ = Ports.(map[uint32]PonPort)
180
181 return &StatMgr
182}
183
184func InitPorts(Intftype string, DeviceID string) (interface{}, error) {
185 /*
186 This method collects the port objects: nni and pon that are updated with the
187 current data from the OLT
188
189 Both the northbound (nni) and southbound ports are indexed by the interface id (intf_id)
190 and NOT the port number. When the port object is instantiated it will contain the intf_id and
191 port_no values
192
193 :param type:
194 :return:
195 */
196 var i uint32
197 if Intftype == "nni" {
198 NniPorts := make(map[uint32]NniPort)
199 for i = 0; i <= 1; i++ {
200 Port := BuildPortObject(i, "nni", DeviceID).(NniPort)
201 NniPorts[Port.IntfID] = Port
202 }
203 return NniPorts, nil
204 } else if Intftype == "pon" {
205 PONPorts := make(map[uint32]PonPort)
206 for i = 0; i <= 16; i++ {
207 PONPort := BuildPortObject(i, "pon", DeviceID).(PonPort)
208 PONPorts[PONPort.IntfID] = PONPort
209 }
210 return PONPorts, nil
211 } else {
212 log.Errorf("Invalid type of interface %s", Intftype)
213 return nil, errors.New("Invalid type of interface ")
214 }
215}
216
217func BuildPortObject(PortNum uint32, IntfType string, DeviceID string) interface{} {
218 /*
219 Seperate method to allow for updating north and southbound ports
220 newly discovered ports and devices
221
222 :param port_num:
223 :param type:
224 :return:
225 */
226
227 //This builds a port object which is added to the
228 //appropriate northbound or southbound values
229 if IntfType == "nni" {
230 IntfID := IntfIdToPortNo(PortNum, voltha.Port_ETHERNET_UNI)
231 return NewNniPort(PortNum, IntfID)
232 } else if IntfType == "pon" {
233 // PON ports require a different configuration
234 // intf_id and pon_id are currently equal.
235 IntfID := IntfIdToPortNo(PortNum, voltha.Port_ETHERNET_NNI)
236 PONID := IntfID
237 return NewPONPort(PONID, DeviceID, IntfID, PortNum)
238 } else {
239 log.Errorf("Invalid type of interface %s", IntfType)
240 return nil
241 }
242}
243
244func (StatMgr *OpenOltStatisticsMgr) PortStatisticsIndication(PortStats *openolt.PortStatistics) {
245 log.Debugf("port-stats-collected %v", PortStats)
246 StatMgr.PortsStatisticsKpis(PortStats)
247 // TODO send stats to core topic to the voltha kafka or a different kafka ?
248}
249
250func FlowStatisticsIndication(self, FlowStats *openolt.FlowStatistics) {
251 log.Debugf("flow-stats-collected %v", FlowStats)
252 //TODO send to kafka ?
253}
254
255func (StatMgr *OpenOltStatisticsMgr) PortsStatisticsKpis(PortStats *openolt.PortStatistics) {
256
257 /*map the port stats values into a dictionary
258 Create a kpoEvent and publish to Kafka
259
260 :param port_stats:
261 :return:
262 */
263 //var err error
264 IntfID := PortStats.IntfId
265
266 if (IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) < IntfID) &&
267 (IntfID < IntfIdToPortNo(4, voltha.Port_ETHERNET_NNI)) {
268 /*
269 for this release we are only interested in the first NNI for
270 Northbound.
271 we are not using the other 3
272 */
273 return
274 } else {
275
276 PMData := make(map[string]uint64)
277 PMData["rx_bytes"] = PortStats.RxBytes
278 PMData["rx_packets"] = PortStats.RxPackets
279 PMData["rx_ucast_packets"] = PortStats.RxUcastPackets
280 PMData["rx_mcast_packets"] = PortStats.RxMcastPackets
281 PMData["rx_bcast_packets"] = PortStats.RxBcastPackets
282 PMData["rx_error_packets"] = PortStats.RxErrorPackets
283 PMData["tx_bytes"] = PortStats.TxBytes
284 PMData["tx_packets"] = PortStats.TxPackets
285 PMData["tx_ucast_packets"] = PortStats.TxUcastPackets
286 PMData["tx_mcast_packets"] = PortStats.TxMcastPackets
287 PMData["tx_bcast_packets"] = PortStats.TxBcastPackets
288 PMData["tx_error_packets"] = PortStats.TxErrorPackets
289 PMData["rx_crc_errors"] = PortStats.RxCrcErrors
290 PMData["bip_errors"] = PortStats.BipErrors
291
292 PMData["intf_id"] = uint64(PortStats.IntfId)
293
294 /*
295 Based upon the intf_id map to an nni port or a pon port
296 the intf_id is the key to the north or south bound collections
297
298 Based upon the intf_id the port object (nni_port or pon_port) will
299 have its data attr. updated by the current dataset collected.
300
301 For prefixing the rule is currently to use the port number and not the intf_id
302 */
303 //FIXME : Just use first NNI for now
304 /* TODO should the data be marshalled before sending it ?
305 if IntfID == IntfIdToPortNo(0, voltha.Port_ETHERNET_NNI) {
306 //NNI port (just the first one)
307 err = UpdatePortObjectKpiData(StatMgr.NorthBoundPorts[PortStats.IntfID], PMData)
308 } else {
309 //PON ports
310 err = UpdatePortObjectKpiData(SouthboundPorts[PortStats.IntfID], PMData)
311 }
312 if (err != nil) {
313 log.Error("Error publishing statistics data")
314 }
315 */
316 }
317}