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