blob: 1f9898fa38016b0521dd61589d41bd25184c6f56 [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
dbainbri4d3a0dc2020-12-02 00:33:42 +000020import "context"
21
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000022//Attention: this file is more or less a coopy of file olt_platform.go from the voltha-openolt-adapter
23// which includes system wide definitions and thus normally should be stored more centrally (within some voltha libs)!!
24
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +000025/*=====================================================================
26
27@TODO: Looks like this Flow id concept below is not used anywhere
28 Propose to remove the below documentation of Flow Id on confirmation
29 of the same
30
31Flow id
32
33 Identifies a flow within a single OLT
34 Flow Id is unique per OLT
35 Multiple GEM ports can map to same flow id
36
37 13 11 4 0
38 +--------+--------------+------+
39 | pon id | onu id | Flow |
40 | | | idx |
41 +--------+--------------+------+
42
43 14 bits = 16384 flows (per OLT).
44
45 pon id = 4 bits = 16 PON ports
46 onu id = 7 bits = 128 ONUss per PON port
47 Flow index = 3 bits = 4 bi-directional flows per ONU
48 = 8 uni-directional flows per ONU
49
50
51Logical (OF) UNI port number
52
53 OpenFlow port number corresponding to PON UNI
54
55 20 12 4 0
56 +--+--------+--------------+------+
57 |0 | pon id | onu id |uni id|
58 +--+--------+--------------+------+
59
60 pon id = 8 bits = 256 PON ports
61 onu id = 8 bits = 256 ONUs per PON port
62
63Logical (OF) NNI port number
64
65 OpenFlow port number corresponding to PON NNI
66
67 20 0
68 +--+----------------------------+
69 |1 | intf_id |
70 +--+----------------------------+
71
72 No overlap with UNI port number space
73
74
75PON OLT (OF) port number
76
77 OpenFlow port number corresponding to PON OLT ports
78
79 31 28 0
80 +--------+------------------------~~~------+
81 | 0x2 | pon intf id |
82 +--------+------------------------~~~------+
83*/
84
85const (
86 // Number of bits for the physical UNI of the ONUs
87 bitsForUniID = 4
88 // Number of bits for the ONU ID
89 bitsForONUID = 8
90 // Number of bits for PON ID
91 bitsForPONID = 8
Himani Chawla4d908332020-08-31 12:30:20 +053092 /*
93 // Number of bits to differentiate between UNI and NNI Logical Port
94 bitsForUNINNIDiff = 1
95 */
Himani Chawla6d2ae152020-09-02 13:11:20 +053096 //maxOnusPerPon is Max number of ONUs on any PON port
97 maxOnusPerPon = (1 << bitsForONUID)
98 //maxPonsPerOlt is Max number of PON ports on any OLT
99 maxPonsPerOlt = (1 << bitsForPONID)
100 //maxUnisPerOnu is the Max number of UNI ports on any ONU
101 maxUnisPerOnu = (1 << bitsForUniID)
102 /*
103 //Bit position where the differentiation bit is located
104 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
105 //Bit position where the marker for PON port type of OF port is present
106 ponIntfMarkerPos = 28
107 //Value of marker used to distinguish PON port type of OF port
108 ponIntfMarkerValue = 0x2
109 // Number of bits for NNI ID
110 bitsforNNIID = 20
111 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
112 minNniIntPortNum = (1 << bitsforNNIID)
113 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
114 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
115 */
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000116)
117
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000118//Mask to indicate which possibly active ONU UNI state is really reported to the core
119// compare python code - at the moment restrict active state to the first ONU UNI port
120// check is limited to max 16 uni ports - cmp above UNI limit!!!
Himani Chawla6d2ae152020-09-02 13:11:20 +0530121var activeUniPortStateUpdateMask = 0x0001
Holger Hildebrandtbe674422020-05-05 13:05:30 +0000122
Himani Chawla6d2ae152020-09-02 13:11:20 +0530123/*
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000124//MinUpstreamPortID value
Himani Chawla6d2ae152020-09-02 13:11:20 +0530125var minUpstreamPortID = 0xfffd
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000126
127//MaxUpstreamPortID value
Himani Chawla6d2ae152020-09-02 13:11:20 +0530128var maxUpstreamPortID = 0xfffffffd
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000129
130var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
Himani Chawla6d2ae152020-09-02 13:11:20 +0530131*/
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000132
Holger Hildebrandt47555e72020-09-21 11:07:24 +0000133//mkUniPortNum returns new UNIportNum based on intfID, onuID and uniID
dbainbri4d3a0dc2020-12-02 00:33:42 +0000134func mkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000135 //extended for checks available in the python onu adapter:!!
136 var limit = int(intfID)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530137 if limit > maxPonsPerOlt {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000138 logger.Warn(ctx, "Warning: exceeded the MAX pons per OLT")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000139 }
140 limit = int(onuID)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530141 if limit > maxOnusPerPon {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000142 logger.Warn(ctx, "Warning: exceeded the MAX ONUS per PON")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000143 }
144 limit = int(uniID)
Himani Chawla6d2ae152020-09-02 13:11:20 +0530145 if limit > maxUnisPerOnu {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000146 logger.Warn(ctx, "Warning: exceeded the MAX UNIS per ONU")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000147 }
148 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
149}
150
Himani Chawla6d2ae152020-09-02 13:11:20 +0530151/*
152//onuIDFromPortNum returns ONUID derived from portNumber
153func onuIDFromPortNum(portNum uint32) uint32 {
154 return (portNum >> bitsForUniID) & (maxOnusPerPon - 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000155}
156
Himani Chawla6d2ae152020-09-02 13:11:20 +0530157//intfIDFromUniPortNum returns IntfID derived from portNum
158func intfIDFromUniPortNum(portNum uint32) uint32 {
159 return (portNum >> (bitsForUniID + bitsForONUID)) & (maxPonsPerOlt - 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000160}
161
Himani Chawla6d2ae152020-09-02 13:11:20 +0530162//uniIDFromPortNum return UniID derived from portNum
163func uniIDFromPortNum(portNum uint32) uint32 {
164 return (portNum) & (maxUnisPerOnu - 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000165}
166
Himani Chawla6d2ae152020-09-02 13:11:20 +0530167//intfIDToPortNo returns portId derived from intftype, intfId and portType
168func intfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000169 if (intfType) == voltha.Port_ETHERNET_NNI {
170 return (1 << nniUniDiffPos) | intfID
171 }
172 if (intfType) == voltha.Port_PON_OLT {
173 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
174 }
175 return 0
176}
177
Himani Chawla6d2ae152020-09-02 13:11:20 +0530178//portNoToIntfID returns portnumber derived from interfaceID
179func portNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000180 if (intfType) == voltha.Port_ETHERNET_NNI {
181 return (1 << nniUniDiffPos) ^ portno
182 }
183 if (intfType) == voltha.Port_PON_OLT {
184 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
185 }
186 return 0
187}
188
Himani Chawla6d2ae152020-09-02 13:11:20 +0530189//intfIDFromNniPortNum returns Intf ID derived from portNum
190func intfIDFromNniPortNum(portNum uint32) (uint32, error) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000191 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
dbainbri4d3a0dc2020-12-02 00:33:42 +0000192 logger.Errorw(ctx,"NNIPortNumber is not in valid range", log.Fields{"portNum": portNum})
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000193 return uint32(0), errors.New("invalid-port-range") //olterrors.ErrInvalidPortRange
194 }
195 return (portNum & 0xFFFF), nil
196}
197
Himani Chawla6d2ae152020-09-02 13:11:20 +0530198//intfIDToPortTypeName returns port type derived from the intfId
199func intfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
200 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < maxPonsPerOlt {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000201 return voltha.Port_PON_OLT
202 }
203 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
204 return voltha.Port_ETHERNET_NNI
205 }
206 return voltha.Port_ETHERNET_UNI
207}
208
Himani Chawla6d2ae152020-09-02 13:11:20 +0530209//extractAccessFromFlow returns AccessDevice information
210func extractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
211 if isUpstream(outPort) {
212 return inPort, intfIDFromUniPortNum(inPort), onuIDFromPortNum(inPort), uniIDFromPortNum(inPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000213 }
Himani Chawla6d2ae152020-09-02 13:11:20 +0530214 return outPort, intfIDFromUniPortNum(outPort), onuIDFromPortNum(outPort), uniIDFromPortNum(outPort)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000215}
216
Himani Chawla6d2ae152020-09-02 13:11:20 +0530217//isUpstream returns true for Upstream and false for downstream
218func isUpstream(outPort uint32) bool {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000219 for _, port := range controllerPorts {
220 if port == outPort {
221 return true
222 }
223 }
224 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
225}
226
Himani Chawla6d2ae152020-09-02 13:11:20 +0530227//isControllerBoundFlow returns true/false
228func isControllerBoundFlow(outPort uint32) bool {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000229 for _, port := range controllerPorts {
230 if port == outPort {
231 return true
232 }
233 }
234 return false
235}
236
Himani Chawla6d2ae152020-09-02 13:11:20 +0530237//onuIDFromUniPortNum returns onuId from give portNum information.
238func onuIDFromUniPortNum(portNum uint32) uint32 {
239 return (portNum >> bitsForUniID) & (maxOnusPerPon - 1)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000240}
241
Himani Chawla6d2ae152020-09-02 13:11:20 +0530242//flowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
243func flowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000244 var uniPortNo uint32
245 var ponIntf uint32
246 var onuID uint32
247 var uniID uint32
248 var inPort uint32
249 var ethType uint32
250
251 if flowDirection == "upstream" {
252 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
253 for _, field := range flows.GetOfbFields(flow) {
254 if field.GetType() == flows.IN_PORT {
255 uniPortNo = field.GetPort()
256 break
257 }
258 }
259 }
260 } else if flowDirection == "downstream" {
261 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
262 for _, field := range flows.GetOfbFields(flow) {
263 if field.GetType() == flows.METADATA {
264 for _, action := range flows.GetActions(flow) {
265 if action.Type == flows.OUTPUT {
266 if out := action.GetOutput(); out != nil {
267 uniPortNo = out.GetPort()
268 }
269 break
270 }
271 }
272 } else if field.GetType() == flows.IN_PORT {
273 inPort = field.GetPort()
274 } else if field.GetType() == flows.ETH_TYPE {
275 ethType = field.GetEthType()
276 }
277 }
278 }
279 }
280
281 if uniPortNo == 0 {
Himani Chawla6d2ae152020-09-02 13:11:20 +0530282 return 0, 0, 0, 0, 0, 0, errors.New("notFound: pon-interface (flowDirection)")
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000283 // olterrors.NewErrNotFound("pon-interface", log.Fields{"flow-direction": flowDirection}, nil)
284 }
285
Himani Chawla6d2ae152020-09-02 13:11:20 +0530286 ponIntf = intfIDFromUniPortNum(uniPortNo)
287 onuID = onuIDFromUniPortNum(uniPortNo)
288 uniID = uniIDFromPortNum(uniPortNo)
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000289
dbainbri4d3a0dc2020-12-02 00:33:42 +0000290 logger.Debugw(ctx,"flow extract info result",
Holger Hildebrandt0f9b88d2020-04-20 13:33:25 +0000291 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
292 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
293
294 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
295}
Himani Chawla6d2ae152020-09-02 13:11:20 +0530296*/