blob: 7e6469c067eb18cc57b22c0bd9de5040cae1713a [file] [log] [blame]
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +00001/*
2 * Copyright 2018-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 */
16
Himani Chawla4d908332020-08-31 12:30:20 +053017//Package adaptercoreonu provides the utility for onu devices, flows and statistics
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000018package adaptercoreonu
19
20//Attention: this file is more or less a coopy of file olt_platform.go from the voltha-openolt-adapter
21// which includes system wide definitions and thus normally should be stored more centrally (within some voltha libs)!!
22
23import (
24 "errors"
25
26 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
27 "github.com/opencord/voltha-lib-go/v3/pkg/log"
28
29 //"github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
30 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
31 "github.com/opencord/voltha-protos/v3/go/voltha"
32)
33
34/*=====================================================================
35
36@TODO: Looks like this Flow id concept below is not used anywhere
37 Propose to remove the below documentation of Flow Id on confirmation
38 of the same
39
40Flow id
41
42 Identifies a flow within a single OLT
43 Flow Id is unique per OLT
44 Multiple GEM ports can map to same flow id
45
46 13 11 4 0
47 +--------+--------------+------+
48 | pon id | onu id | Flow |
49 | | | idx |
50 +--------+--------------+------+
51
52 14 bits = 16384 flows (per OLT).
53
54 pon id = 4 bits = 16 PON ports
55 onu id = 7 bits = 128 ONUss per PON port
56 Flow index = 3 bits = 4 bi-directional flows per ONU
57 = 8 uni-directional flows per ONU
58
59
60Logical (OF) UNI port number
61
62 OpenFlow port number corresponding to PON UNI
63
64 20 12 4 0
65 +--+--------+--------------+------+
66 |0 | pon id | onu id |uni id|
67 +--+--------+--------------+------+
68
69 pon id = 8 bits = 256 PON ports
70 onu id = 8 bits = 256 ONUs per PON port
71
72Logical (OF) NNI port number
73
74 OpenFlow port number corresponding to PON NNI
75
76 20 0
77 +--+----------------------------+
78 |1 | intf_id |
79 +--+----------------------------+
80
81 No overlap with UNI port number space
82
83
84PON OLT (OF) port number
85
86 OpenFlow port number corresponding to PON OLT ports
87
88 31 28 0
89 +--------+------------------------~~~------+
90 | 0x2 | pon intf id |
91 +--------+------------------------~~~------+
92*/
93
94const (
95 // Number of bits for the physical UNI of the ONUs
96 bitsForUniID = 4
97 // Number of bits for the ONU ID
98 bitsForONUID = 8
99 // Number of bits for PON ID
100 bitsForPONID = 8
Himani Chawla4d908332020-08-31 12:30:20 +0530101 /*
102 // Number of bits to differentiate between UNI and NNI Logical Port
103 bitsForUNINNIDiff = 1
104 */
105
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000106 //MaxOnusPerPon is Max number of ONUs on any PON port
107 MaxOnusPerPon = (1 << bitsForONUID)
108 //MaxPonsPerOlt is Max number of PON ports on any OLT
109 MaxPonsPerOlt = (1 << bitsForPONID)
110 //MaxUnisPerOnu is the Max number of UNI ports on any ONU
111 MaxUnisPerOnu = (1 << bitsForUniID)
112 //Bit position where the differentiation bit is located
113 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
114 //Bit position where the marker for PON port type of OF port is present
115 ponIntfMarkerPos = 28
116 //Value of marker used to distinguish PON port type of OF port
117 ponIntfMarkerValue = 0x2
118 // Number of bits for NNI ID
119 bitsforNNIID = 20
120 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
121 minNniIntPortNum = (1 << bitsforNNIID)
122 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
123 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
124)
125
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000126//Mask to indicate which possibly active ONU UNI state is really reported to the core
127// compare python code - at the moment restrict active state to the first ONU UNI port
128// check is limited to max 16 uni ports - cmp above UNI limit!!!
129var ActiveUniPortStateUpdateMask = 0x0001
130
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000131//MinUpstreamPortID value
132var MinUpstreamPortID = 0xfffd
133
134//MaxUpstreamPortID value
135var MaxUpstreamPortID = 0xfffffffd
136
137var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
138
139//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
140func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
141 //extended for checks available in the python onu adapter:!!
142 var limit = int(intfID)
143 if limit > MaxPonsPerOlt {
144 logger.Warn("Warning: exceeded the MAX pons per OLT")
145 }
146 limit = int(onuID)
147 if limit > MaxOnusPerPon {
148 logger.Warn("Warning: exceeded the MAX ONUS per PON")
149 }
150 limit = int(uniID)
151 if limit > MaxUnisPerOnu {
152 logger.Warn("Warning: exceeded the MAX UNIS per ONU")
153 }
154 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
155}
156
157//OnuIDFromPortNum returns ONUID derived from portNumber
158func OnuIDFromPortNum(portNum uint32) uint32 {
159 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
160}
161
162//IntfIDFromUniPortNum returns IntfID derived from portNum
163func IntfIDFromUniPortNum(portNum uint32) uint32 {
164 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
165}
166
167//UniIDFromPortNum return UniID derived from portNum
168func UniIDFromPortNum(portNum uint32) uint32 {
169 return (portNum) & (MaxUnisPerOnu - 1)
170}
171
172//IntfIDToPortNo returns portId derived from intftype, intfId and portType
173func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
174 if (intfType) == voltha.Port_ETHERNET_NNI {
175 return (1 << nniUniDiffPos) | intfID
176 }
177 if (intfType) == voltha.Port_PON_OLT {
178 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
179 }
180 return 0
181}
182
183//PortNoToIntfID returns portnumber derived from interfaceID
184func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
185 if (intfType) == voltha.Port_ETHERNET_NNI {
186 return (1 << nniUniDiffPos) ^ portno
187 }
188 if (intfType) == voltha.Port_PON_OLT {
189 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
190 }
191 return 0
192}
193
194//IntfIDFromNniPortNum returns Intf ID derived from portNum
195func IntfIDFromNniPortNum(portNum uint32) (uint32, error) {
196 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
197 logger.Errorw("NNIPortNumber is not in valid range", log.Fields{"portNum": portNum})
198 return uint32(0), errors.New("invalid-port-range") //olterrors.ErrInvalidPortRange
199 }
200 return (portNum & 0xFFFF), nil
201}
202
203//IntfIDToPortTypeName returns port type derived from the intfId
204func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
205 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
206 return voltha.Port_PON_OLT
207 }
208 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
209 return voltha.Port_ETHERNET_NNI
210 }
211 return voltha.Port_ETHERNET_UNI
212}
213
214//ExtractAccessFromFlow returns AccessDevice information
215func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
216 if IsUpstream(outPort) {
217 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
218 }
219 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
220}
221
222//IsUpstream returns true for Upstream and false for downstream
223func IsUpstream(outPort uint32) bool {
224 for _, port := range controllerPorts {
225 if port == outPort {
226 return true
227 }
228 }
229 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
230}
231
232//IsControllerBoundFlow returns true/false
233func IsControllerBoundFlow(outPort uint32) bool {
234 for _, port := range controllerPorts {
235 if port == outPort {
236 return true
237 }
238 }
239 return false
240}
241
242//OnuIDFromUniPortNum returns onuId from give portNum information.
243func OnuIDFromUniPortNum(portNum uint32) uint32 {
244 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
245}
246
247//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
248func FlowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
249 var uniPortNo uint32
250 var ponIntf uint32
251 var onuID uint32
252 var uniID uint32
253 var inPort uint32
254 var ethType uint32
255
256 if flowDirection == "upstream" {
257 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
258 for _, field := range flows.GetOfbFields(flow) {
259 if field.GetType() == flows.IN_PORT {
260 uniPortNo = field.GetPort()
261 break
262 }
263 }
264 }
265 } else if flowDirection == "downstream" {
266 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
267 for _, field := range flows.GetOfbFields(flow) {
268 if field.GetType() == flows.METADATA {
269 for _, action := range flows.GetActions(flow) {
270 if action.Type == flows.OUTPUT {
271 if out := action.GetOutput(); out != nil {
272 uniPortNo = out.GetPort()
273 }
274 break
275 }
276 }
277 } else if field.GetType() == flows.IN_PORT {
278 inPort = field.GetPort()
279 } else if field.GetType() == flows.ETH_TYPE {
280 ethType = field.GetEthType()
281 }
282 }
283 }
284 }
285
286 if uniPortNo == 0 {
287 return 0, 0, 0, 0, 0, 0, errors.New("NotFound: pon-interface (flowDirection)")
288 // olterrors.NewErrNotFound("pon-interface", log.Fields{"flow-direction": flowDirection}, nil)
289 }
290
291 ponIntf = IntfIDFromUniPortNum(uniPortNo)
292 onuID = OnuIDFromUniPortNum(uniPortNo)
293 uniID = UniIDFromPortNum(uniPortNo)
294
295 logger.Debugw("flow extract info result",
296 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
297 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
298
299 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
300}