blob: 688ccd8bf26c7011b1789a9cde092f89818b2dbe [file] [log] [blame]
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -07001/*
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
17package platform
18
19import (
20 "context"
21
22 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
23 "github.com/opencord/voltha-lib-go/v7/pkg/log"
24 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
25 "github.com/opencord/voltha-protos/v5/go/voltha"
26 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
28)
29
30/*=====================================================================
31Logical (OF) UNI port number
32
33 OpenFlow port number corresponding to PON UNI
34
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070035 24 16 8 0
36 +--+--------+----------+----------+
37 |0 | pon id | onu id | uni id |
38 +--+--------+----------+----------+
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070039
40 pon id = 8 bits = 256 PON ports
41 onu id = 8 bits = 256 ONUs per PON port
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070042 uni id = 8 bits = 256 UNIs per ONU
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070043
44Logical (OF) NNI port number
45
46 OpenFlow port number corresponding to PON NNI
47
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070048 24 0
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070049 +--+----------------------------+
50 |1 | intf_id |
51 +--+----------------------------+
52
53 No overlap with UNI port number space
54
55
56PON OLT (OF) port number
57
58 OpenFlow port number corresponding to PON OLT ports
59
60 31 28 0
61 +--------+------------------------~~~------+
62 | 0x2 | pon intf id |
63 +--------+------------------------~~~------+
64*/
65
66const (
67 // Number of bits for the physical UNI of the ONUs
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070068 bitsForUniID = 8
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070069 // Number of bits for the ONU ID
70 bitsForONUID = 8
71 // Number of bits for PON ID
72 bitsForPONID = 8
73 // MaxOnusPerPon is Max number of ONUs on any PON port
74 MaxOnusPerPon = (1 << bitsForONUID)
75 // MaxPonsPerOlt is Max number of PON ports on any OLT
76 MaxPonsPerOlt = (1 << bitsForPONID)
77 // MaxUnisPerOnu is the Max number of UNI ports on any ONU
78 MaxUnisPerOnu = (1 << bitsForUniID)
79 // Bit position where the differentiation bit is located
80 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
81 // Bit position where the marker for PON port type of OF port is present
82 ponIntfMarkerPos = 28
83 // Value of marker used to distinguish PON port type of OF port
84 ponIntfMarkerValue = 0x2
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070085 // minNniPortNum is used to store start range of nni port number (1 << 24) 16777216
86 minNniPortNum = (1 << nniUniDiffPos)
87 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 25)-1) 33554431
88 maxNniPortNum = ((1 << (nniUniDiffPos + 1)) - 1)
89 // minPonIntfPortNum stores the minimum pon port number (536870912)
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070090 minPonIntfPortNum = ponIntfMarkerValue << ponIntfMarkerPos
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070091 // maxPonIntfPortNum stores the maximum pon port number (536871167)
92 maxPonIntfPortNum = ((ponIntfMarkerValue << ponIntfMarkerPos) | (1 << bitsForPONID)) - 1
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -070093 upstream = "upstream"
94 downstream = "downstream"
Mahir Gunyela8ab55f2021-10-20 15:07:25 -070095 //Technology Profiles ID start value
96 TpIDStart = 64
97 //Technology Profiles ID end value
98 TpIDEnd = 256
99 //Number of Technology Profiles can be defined.
100 TpRange = TpIDEnd - TpIDStart
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700101)
102
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700103var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
104
105//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
106func MkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700107 var limit = int(intfID)
108 if limit > MaxPonsPerOlt {
109 logger.Warn(ctx, "Warning: exceeded the MAX pons per OLT")
110 }
111 limit = int(onuID)
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700112 if limit > MaxOnusPerPon {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700113 logger.Warn(ctx, "Warning: exceeded the MAX ONUS per PON")
114 }
115 limit = int(uniID)
116 if limit > MaxUnisPerOnu {
117 logger.Warn(ctx, "Warning: exceeded the MAX UNIS per ONU")
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700118 }
119 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
120}
121
122//OnuIDFromPortNum returns ONUID derived from portNumber
123func OnuIDFromPortNum(portNum uint32) uint32 {
124 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
125}
126
127//IntfIDFromUniPortNum returns IntfID derived from portNum
128func IntfIDFromUniPortNum(portNum uint32) uint32 {
129 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
130}
131
132//UniIDFromPortNum return UniID derived from portNum
133func UniIDFromPortNum(portNum uint32) uint32 {
134 return (portNum) & (MaxUnisPerOnu - 1)
135}
136
137//IntfIDToPortNo returns portId derived from intftype, intfId and portType
138func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
139 if (intfType) == voltha.Port_ETHERNET_NNI {
140 return (1 << nniUniDiffPos) | intfID
141 }
142 if (intfType) == voltha.Port_PON_OLT {
143 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
144 }
145 return 0
146}
147
148//PortNoToIntfID returns portnumber derived from interfaceID
149func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
150 if (intfType) == voltha.Port_ETHERNET_NNI {
151 return (1 << nniUniDiffPos) ^ portno
152 }
153 if (intfType) == voltha.Port_PON_OLT {
154 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
155 }
156 return 0
157}
158
159//IntfIDFromNniPortNum returns Intf ID derived from portNum
160func IntfIDFromNniPortNum(ctx context.Context, portNum uint32) (uint32, error) {
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700161 if portNum < minNniPortNum || portNum > maxNniPortNum {
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700162 logger.Errorw(ctx, "nniportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
163 return uint32(0), status.Errorf(codes.InvalidArgument, "nni-port-number-out-of-range:%d", portNum)
164 }
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700165 return (portNum & (minNniPortNum - 1)), nil
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700166}
167
168//IntfIDFromPonPortNum returns Intf ID derived from portNum
169func IntfIDFromPonPortNum(ctx context.Context, portNum uint32) (uint32, error) {
170 if portNum < minPonIntfPortNum || portNum > maxPonIntfPortNum {
171 logger.Errorw(ctx, "ponportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
172 return uint32(0), status.Errorf(codes.InvalidArgument, "invalid-pon-port-number:%d", portNum)
173 }
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700174 return (portNum & ((1 << ponIntfMarkerPos) - 1)), nil
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700175}
176
177//IntfIDToPortTypeName returns port type derived from the intfId
178func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
179 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
180 return voltha.Port_PON_OLT
181 }
182 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
183 return voltha.Port_ETHERNET_NNI
184 }
185 return voltha.Port_ETHERNET_UNI
186}
187
188//ExtractAccessFromFlow returns AccessDevice information
189func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
190 if IsUpstream(outPort) {
191 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
192 }
193 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
194}
195
196//IsUpstream returns true for Upstream and false for downstream
197func IsUpstream(outPort uint32) bool {
198 for _, port := range controllerPorts {
199 if port == outPort {
200 return true
201 }
202 }
203 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
204}
205
206//IsControllerBoundFlow returns true/false
207func IsControllerBoundFlow(outPort uint32) bool {
208 for _, port := range controllerPorts {
209 if port == outPort {
210 return true
211 }
212 }
213 return false
214}
215
216//OnuIDFromUniPortNum returns onuId from give portNum information.
217func OnuIDFromUniPortNum(portNum uint32) uint32 {
218 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
219}
220
221//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
222func FlowExtractInfo(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
223 var uniPortNo uint32
224 var ponIntf uint32
225 var onuID uint32
226 var uniID uint32
227 var inPort uint32
228 var ethType uint32
229
230 if flowDirection == upstream {
231 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
232 for _, field := range flows.GetOfbFields(flow) {
233 if field.GetType() == flows.IN_PORT {
234 uniPortNo = field.GetPort()
235 break
236 }
237 }
238 }
239 } else if flowDirection == downstream {
240 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
241 for _, field := range flows.GetOfbFields(flow) {
242 if field.GetType() == flows.METADATA {
243 for _, action := range flows.GetActions(flow) {
244 if action.Type == flows.OUTPUT {
245 if out := action.GetOutput(); out != nil {
246 uniPortNo = out.GetPort()
247 }
248 break
249 }
250 }
251 } else if field.GetType() == flows.IN_PORT {
252 inPort = field.GetPort()
253 } else if field.GetType() == flows.ETH_TYPE {
254 ethType = field.GetEthType()
255 }
256 }
257 }
258 }
259
260 if uniPortNo == 0 {
261 return 0, 0, 0, 0, 0, 0, status.Errorf(codes.NotFound, "uni-not-found-flow-diraction:%s", flowDirection)
262 }
263
264 ponIntf = IntfIDFromUniPortNum(uniPortNo)
265 onuID = OnuIDFromUniPortNum(uniPortNo)
266 uniID = UniIDFromPortNum(uniPortNo)
267
268 logger.Debugw(ctx, "flow-extract-info-result",
269 log.Fields{
270 "uniportno": uniPortNo,
271 "pon-intf": ponIntf,
272 "onu-id": onuID,
273 "uni-id": uniID,
274 "inport": inPort,
275 "ethtype": ethType})
276
277 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
278}