blob: 0fe3956a740530cee340a5916de0a0e0ac3f92bc [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 -0700103//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
104func MkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700105 var limit = int(intfID)
106 if limit > MaxPonsPerOlt {
107 logger.Warn(ctx, "Warning: exceeded the MAX pons per OLT")
108 }
109 limit = int(onuID)
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700110 if limit > MaxOnusPerPon {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700111 logger.Warn(ctx, "Warning: exceeded the MAX ONUS per PON")
112 }
113 limit = int(uniID)
114 if limit > MaxUnisPerOnu {
115 logger.Warn(ctx, "Warning: exceeded the MAX UNIS per ONU")
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700116 }
117 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
118}
119
120//OnuIDFromPortNum returns ONUID derived from portNumber
121func OnuIDFromPortNum(portNum uint32) uint32 {
122 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
123}
124
125//IntfIDFromUniPortNum returns IntfID derived from portNum
126func IntfIDFromUniPortNum(portNum uint32) uint32 {
127 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
128}
129
130//UniIDFromPortNum return UniID derived from portNum
131func UniIDFromPortNum(portNum uint32) uint32 {
132 return (portNum) & (MaxUnisPerOnu - 1)
133}
134
135//IntfIDToPortNo returns portId derived from intftype, intfId and portType
136func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
137 if (intfType) == voltha.Port_ETHERNET_NNI {
138 return (1 << nniUniDiffPos) | intfID
139 }
140 if (intfType) == voltha.Port_PON_OLT {
141 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
142 }
143 return 0
144}
145
146//PortNoToIntfID returns portnumber derived from interfaceID
147func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
148 if (intfType) == voltha.Port_ETHERNET_NNI {
149 return (1 << nniUniDiffPos) ^ portno
150 }
151 if (intfType) == voltha.Port_PON_OLT {
152 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
153 }
154 return 0
155}
156
157//IntfIDFromNniPortNum returns Intf ID derived from portNum
158func IntfIDFromNniPortNum(ctx context.Context, portNum uint32) (uint32, error) {
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700159 if portNum < minNniPortNum || portNum > maxNniPortNum {
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700160 logger.Errorw(ctx, "nniportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
161 return uint32(0), status.Errorf(codes.InvalidArgument, "nni-port-number-out-of-range:%d", portNum)
162 }
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700163 return (portNum & (minNniPortNum - 1)), nil
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700164}
165
166//IntfIDFromPonPortNum returns Intf ID derived from portNum
167func IntfIDFromPonPortNum(ctx context.Context, portNum uint32) (uint32, error) {
168 if portNum < minPonIntfPortNum || portNum > maxPonIntfPortNum {
169 logger.Errorw(ctx, "ponportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
170 return uint32(0), status.Errorf(codes.InvalidArgument, "invalid-pon-port-number:%d", portNum)
171 }
Mahir Gunyela8ab55f2021-10-20 15:07:25 -0700172 return (portNum & ((1 << ponIntfMarkerPos) - 1)), nil
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700173}
174
175//IntfIDToPortTypeName returns port type derived from the intfId
176func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
177 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
178 return voltha.Port_PON_OLT
179 }
180 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
181 return voltha.Port_ETHERNET_NNI
182 }
183 return voltha.Port_ETHERNET_UNI
184}
185
186//ExtractAccessFromFlow returns AccessDevice information
187func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
188 if IsUpstream(outPort) {
189 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
190 }
191 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
192}
193
194//IsUpstream returns true for Upstream and false for downstream
195func IsUpstream(outPort uint32) bool {
Mahir Gunyel0d1a40e2021-10-27 16:29:06 -0700196 if IsControllerBoundFlow(outPort) {
197 return true
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700198 }
199 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
200}
201
202//IsControllerBoundFlow returns true/false
203func IsControllerBoundFlow(outPort uint32) bool {
Mahir Gunyel0d1a40e2021-10-27 16:29:06 -0700204 return outPort == uint32(ofp.OfpPortNo_OFPP_CONTROLLER)
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700205}
206
207//OnuIDFromUniPortNum returns onuId from give portNum information.
208func OnuIDFromUniPortNum(portNum uint32) uint32 {
209 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
210}
211
212//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
213func FlowExtractInfo(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
214 var uniPortNo uint32
215 var ponIntf uint32
216 var onuID uint32
217 var uniID uint32
218 var inPort uint32
219 var ethType uint32
220
221 if flowDirection == upstream {
222 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
223 for _, field := range flows.GetOfbFields(flow) {
224 if field.GetType() == flows.IN_PORT {
225 uniPortNo = field.GetPort()
226 break
227 }
228 }
229 }
230 } else if flowDirection == downstream {
231 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
232 for _, field := range flows.GetOfbFields(flow) {
233 if field.GetType() == flows.METADATA {
234 for _, action := range flows.GetActions(flow) {
235 if action.Type == flows.OUTPUT {
236 if out := action.GetOutput(); out != nil {
237 uniPortNo = out.GetPort()
238 }
239 break
240 }
241 }
242 } else if field.GetType() == flows.IN_PORT {
243 inPort = field.GetPort()
244 } else if field.GetType() == flows.ETH_TYPE {
245 ethType = field.GetEthType()
246 }
247 }
248 }
249 }
250
251 if uniPortNo == 0 {
252 return 0, 0, 0, 0, 0, 0, status.Errorf(codes.NotFound, "uni-not-found-flow-diraction:%s", flowDirection)
253 }
254
255 ponIntf = IntfIDFromUniPortNum(uniPortNo)
256 onuID = OnuIDFromUniPortNum(uniPortNo)
257 uniID = UniIDFromPortNum(uniPortNo)
258
259 logger.Debugw(ctx, "flow-extract-info-result",
260 log.Fields{
261 "uniportno": uniPortNo,
262 "pon-intf": ponIntf,
263 "onu-id": onuID,
264 "uni-id": uniID,
265 "inport": inPort,
266 "ethtype": ethType})
267
268 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
269}