blob: 8edf4d1ecb31bc016d3b54a3c925c2f42a2384fa [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
17//Package core provides the utility for olt devices, flows and statistics
18package 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
101 // Number of bits to differentiate between UNI and NNI Logical Port
102 bitsForUNINNIDiff = 1
103 //MaxOnusPerPon is Max number of ONUs on any PON port
104 MaxOnusPerPon = (1 << bitsForONUID)
105 //MaxPonsPerOlt is Max number of PON ports on any OLT
106 MaxPonsPerOlt = (1 << bitsForPONID)
107 //MaxUnisPerOnu is the Max number of UNI ports on any ONU
108 MaxUnisPerOnu = (1 << bitsForUniID)
109 //Bit position where the differentiation bit is located
110 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
111 //Bit position where the marker for PON port type of OF port is present
112 ponIntfMarkerPos = 28
113 //Value of marker used to distinguish PON port type of OF port
114 ponIntfMarkerValue = 0x2
115 // Number of bits for NNI ID
116 bitsforNNIID = 20
117 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
118 minNniIntPortNum = (1 << bitsforNNIID)
119 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
120 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
121)
122
123//MinUpstreamPortID value
124var MinUpstreamPortID = 0xfffd
125
126//MaxUpstreamPortID value
127var MaxUpstreamPortID = 0xfffffffd
128
129var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
130
131//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
132func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
133 //extended for checks available in the python onu adapter:!!
134 var limit = int(intfID)
135 if limit > MaxPonsPerOlt {
136 logger.Warn("Warning: exceeded the MAX pons per OLT")
137 }
138 limit = int(onuID)
139 if limit > MaxOnusPerPon {
140 logger.Warn("Warning: exceeded the MAX ONUS per PON")
141 }
142 limit = int(uniID)
143 if limit > MaxUnisPerOnu {
144 logger.Warn("Warning: exceeded the MAX UNIS per ONU")
145 }
146 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
147}
148
149//OnuIDFromPortNum returns ONUID derived from portNumber
150func OnuIDFromPortNum(portNum uint32) uint32 {
151 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
152}
153
154//IntfIDFromUniPortNum returns IntfID derived from portNum
155func IntfIDFromUniPortNum(portNum uint32) uint32 {
156 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
157}
158
159//UniIDFromPortNum return UniID derived from portNum
160func UniIDFromPortNum(portNum uint32) uint32 {
161 return (portNum) & (MaxUnisPerOnu - 1)
162}
163
164//IntfIDToPortNo returns portId derived from intftype, intfId and portType
165func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
166 if (intfType) == voltha.Port_ETHERNET_NNI {
167 return (1 << nniUniDiffPos) | intfID
168 }
169 if (intfType) == voltha.Port_PON_OLT {
170 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
171 }
172 return 0
173}
174
175//PortNoToIntfID returns portnumber derived from interfaceID
176func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
177 if (intfType) == voltha.Port_ETHERNET_NNI {
178 return (1 << nniUniDiffPos) ^ portno
179 }
180 if (intfType) == voltha.Port_PON_OLT {
181 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
182 }
183 return 0
184}
185
186//IntfIDFromNniPortNum returns Intf ID derived from portNum
187func IntfIDFromNniPortNum(portNum uint32) (uint32, error) {
188 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
189 logger.Errorw("NNIPortNumber is not in valid range", log.Fields{"portNum": portNum})
190 return uint32(0), errors.New("invalid-port-range") //olterrors.ErrInvalidPortRange
191 }
192 return (portNum & 0xFFFF), nil
193}
194
195//IntfIDToPortTypeName returns port type derived from the intfId
196func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
197 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
198 return voltha.Port_PON_OLT
199 }
200 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
201 return voltha.Port_ETHERNET_NNI
202 }
203 return voltha.Port_ETHERNET_UNI
204}
205
206//ExtractAccessFromFlow returns AccessDevice information
207func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
208 if IsUpstream(outPort) {
209 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
210 }
211 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
212}
213
214//IsUpstream returns true for Upstream and false for downstream
215func IsUpstream(outPort uint32) bool {
216 for _, port := range controllerPorts {
217 if port == outPort {
218 return true
219 }
220 }
221 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
222}
223
224//IsControllerBoundFlow returns true/false
225func IsControllerBoundFlow(outPort uint32) bool {
226 for _, port := range controllerPorts {
227 if port == outPort {
228 return true
229 }
230 }
231 return false
232}
233
234//OnuIDFromUniPortNum returns onuId from give portNum information.
235func OnuIDFromUniPortNum(portNum uint32) uint32 {
236 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
237}
238
239//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
240func FlowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
241 var uniPortNo uint32
242 var ponIntf uint32
243 var onuID uint32
244 var uniID uint32
245 var inPort uint32
246 var ethType uint32
247
248 if flowDirection == "upstream" {
249 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
250 for _, field := range flows.GetOfbFields(flow) {
251 if field.GetType() == flows.IN_PORT {
252 uniPortNo = field.GetPort()
253 break
254 }
255 }
256 }
257 } else if flowDirection == "downstream" {
258 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
259 for _, field := range flows.GetOfbFields(flow) {
260 if field.GetType() == flows.METADATA {
261 for _, action := range flows.GetActions(flow) {
262 if action.Type == flows.OUTPUT {
263 if out := action.GetOutput(); out != nil {
264 uniPortNo = out.GetPort()
265 }
266 break
267 }
268 }
269 } else if field.GetType() == flows.IN_PORT {
270 inPort = field.GetPort()
271 } else if field.GetType() == flows.ETH_TYPE {
272 ethType = field.GetEthType()
273 }
274 }
275 }
276 }
277
278 if uniPortNo == 0 {
279 return 0, 0, 0, 0, 0, 0, errors.New("NotFound: pon-interface (flowDirection)")
280 // olterrors.NewErrNotFound("pon-interface", log.Fields{"flow-direction": flowDirection}, nil)
281 }
282
283 ponIntf = IntfIDFromUniPortNum(uniPortNo)
284 onuID = OnuIDFromUniPortNum(uniPortNo)
285 uniID = UniIDFromPortNum(uniPortNo)
286
287 logger.Debugw("flow extract info result",
288 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
289 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
290
291 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
292}