blob: 2aef6e18d58b6806a52024f9b72b898754198bad [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
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000123//Mask to indicate which possibly active ONU UNI state is really reported to the core
124// compare python code - at the moment restrict active state to the first ONU UNI port
125// check is limited to max 16 uni ports - cmp above UNI limit!!!
126var ActiveUniPortStateUpdateMask = 0x0001
127
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000128//MinUpstreamPortID value
129var MinUpstreamPortID = 0xfffd
130
131//MaxUpstreamPortID value
132var MaxUpstreamPortID = 0xfffffffd
133
134var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
135
136//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
137func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
138 //extended for checks available in the python onu adapter:!!
139 var limit = int(intfID)
140 if limit > MaxPonsPerOlt {
141 logger.Warn("Warning: exceeded the MAX pons per OLT")
142 }
143 limit = int(onuID)
144 if limit > MaxOnusPerPon {
145 logger.Warn("Warning: exceeded the MAX ONUS per PON")
146 }
147 limit = int(uniID)
148 if limit > MaxUnisPerOnu {
149 logger.Warn("Warning: exceeded the MAX UNIS per ONU")
150 }
151 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
152}
153
154//OnuIDFromPortNum returns ONUID derived from portNumber
155func OnuIDFromPortNum(portNum uint32) uint32 {
156 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
157}
158
159//IntfIDFromUniPortNum returns IntfID derived from portNum
160func IntfIDFromUniPortNum(portNum uint32) uint32 {
161 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
162}
163
164//UniIDFromPortNum return UniID derived from portNum
165func UniIDFromPortNum(portNum uint32) uint32 {
166 return (portNum) & (MaxUnisPerOnu - 1)
167}
168
169//IntfIDToPortNo returns portId derived from intftype, intfId and portType
170func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
171 if (intfType) == voltha.Port_ETHERNET_NNI {
172 return (1 << nniUniDiffPos) | intfID
173 }
174 if (intfType) == voltha.Port_PON_OLT {
175 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
176 }
177 return 0
178}
179
180//PortNoToIntfID returns portnumber derived from interfaceID
181func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
182 if (intfType) == voltha.Port_ETHERNET_NNI {
183 return (1 << nniUniDiffPos) ^ portno
184 }
185 if (intfType) == voltha.Port_PON_OLT {
186 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
187 }
188 return 0
189}
190
191//IntfIDFromNniPortNum returns Intf ID derived from portNum
192func IntfIDFromNniPortNum(portNum uint32) (uint32, error) {
193 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
194 logger.Errorw("NNIPortNumber is not in valid range", log.Fields{"portNum": portNum})
195 return uint32(0), errors.New("invalid-port-range") //olterrors.ErrInvalidPortRange
196 }
197 return (portNum & 0xFFFF), nil
198}
199
200//IntfIDToPortTypeName returns port type derived from the intfId
201func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
202 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
203 return voltha.Port_PON_OLT
204 }
205 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
206 return voltha.Port_ETHERNET_NNI
207 }
208 return voltha.Port_ETHERNET_UNI
209}
210
211//ExtractAccessFromFlow returns AccessDevice information
212func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
213 if IsUpstream(outPort) {
214 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
215 }
216 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
217}
218
219//IsUpstream returns true for Upstream and false for downstream
220func IsUpstream(outPort uint32) bool {
221 for _, port := range controllerPorts {
222 if port == outPort {
223 return true
224 }
225 }
226 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
227}
228
229//IsControllerBoundFlow returns true/false
230func IsControllerBoundFlow(outPort uint32) bool {
231 for _, port := range controllerPorts {
232 if port == outPort {
233 return true
234 }
235 }
236 return false
237}
238
239//OnuIDFromUniPortNum returns onuId from give portNum information.
240func OnuIDFromUniPortNum(portNum uint32) uint32 {
241 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
242}
243
244//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
245func FlowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
246 var uniPortNo uint32
247 var ponIntf uint32
248 var onuID uint32
249 var uniID uint32
250 var inPort uint32
251 var ethType uint32
252
253 if flowDirection == "upstream" {
254 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
255 for _, field := range flows.GetOfbFields(flow) {
256 if field.GetType() == flows.IN_PORT {
257 uniPortNo = field.GetPort()
258 break
259 }
260 }
261 }
262 } else if flowDirection == "downstream" {
263 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
264 for _, field := range flows.GetOfbFields(flow) {
265 if field.GetType() == flows.METADATA {
266 for _, action := range flows.GetActions(flow) {
267 if action.Type == flows.OUTPUT {
268 if out := action.GetOutput(); out != nil {
269 uniPortNo = out.GetPort()
270 }
271 break
272 }
273 }
274 } else if field.GetType() == flows.IN_PORT {
275 inPort = field.GetPort()
276 } else if field.GetType() == flows.ETH_TYPE {
277 ethType = field.GetEthType()
278 }
279 }
280 }
281 }
282
283 if uniPortNo == 0 {
284 return 0, 0, 0, 0, 0, 0, errors.New("NotFound: pon-interface (flowDirection)")
285 // olterrors.NewErrNotFound("pon-interface", log.Fields{"flow-direction": flowDirection}, nil)
286 }
287
288 ponIntf = IntfIDFromUniPortNum(uniPortNo)
289 onuID = OnuIDFromUniPortNum(uniPortNo)
290 uniID = UniIDFromPortNum(uniPortNo)
291
292 logger.Debugw("flow extract info result",
293 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
294 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
295
296 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
297}