blob: db0d5510af280b9e16e01b26a16885fc5a9b98da [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
35 20 12 4 0
36 +--+--------+--------------+------+
37 |0 | pon id | onu id |uni id|
38 +--+--------+--------------+------+
39
40 pon id = 8 bits = 256 PON ports
41 onu id = 8 bits = 256 ONUs per PON port
42
43Logical (OF) NNI port number
44
45 OpenFlow port number corresponding to PON NNI
46
47 20 0
48 +--+----------------------------+
49 |1 | intf_id |
50 +--+----------------------------+
51
52 No overlap with UNI port number space
53
54
55PON OLT (OF) port number
56
57 OpenFlow port number corresponding to PON OLT ports
58
59 31 28 0
60 +--------+------------------------~~~------+
61 | 0x2 | pon intf id |
62 +--------+------------------------~~~------+
63*/
64
65const (
66 // Number of bits for the physical UNI of the ONUs
67 bitsForUniID = 4
68 // Number of bits for the ONU ID
69 bitsForONUID = 8
70 // Number of bits for PON ID
71 bitsForPONID = 8
72 // MaxOnusPerPon is Max number of ONUs on any PON port
73 MaxOnusPerPon = (1 << bitsForONUID)
74 // MaxPonsPerOlt is Max number of PON ports on any OLT
75 MaxPonsPerOlt = (1 << bitsForPONID)
76 // MaxUnisPerOnu is the Max number of UNI ports on any ONU
77 MaxUnisPerOnu = (1 << bitsForUniID)
78 // Bit position where the differentiation bit is located
79 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
80 // Bit position where the marker for PON port type of OF port is present
81 ponIntfMarkerPos = 28
82 // Value of marker used to distinguish PON port type of OF port
83 ponIntfMarkerValue = 0x2
84 // Number of bits for NNI ID
85 bitsforNNIID = 20
86 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
87 minNniIntPortNum = (1 << bitsforNNIID)
88 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
89 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
90 // minPonIntfPortNum stores the minimum pon port number
91 minPonIntfPortNum = ponIntfMarkerValue << ponIntfMarkerPos
92 // maxPonIntfPortNum stores the maximum pon port number
93 maxPonIntfPortNum = (ponIntfMarkerValue << ponIntfMarkerPos) | (1 << bitsForPONID)
94 upstream = "upstream"
95 downstream = "downstream"
96)
97
98//MinUpstreamPortID value
99var MinUpstreamPortID = 0xfffd
100
101//MaxUpstreamPortID value
102var MaxUpstreamPortID = 0xfffffffd
103
104var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
105
106//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
107func MkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700108 var limit = int(intfID)
109 if limit > MaxPonsPerOlt {
110 logger.Warn(ctx, "Warning: exceeded the MAX pons per OLT")
111 }
112 limit = int(onuID)
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700113 if limit > MaxOnusPerPon {
Mahir Gunyel3692ac42021-10-06 10:12:46 -0700114 logger.Warn(ctx, "Warning: exceeded the MAX ONUS per PON")
115 }
116 limit = int(uniID)
117 if limit > MaxUnisPerOnu {
118 logger.Warn(ctx, "Warning: exceeded the MAX UNIS per ONU")
Mahir Gunyel2c4b96b2021-09-13 17:01:05 -0700119 }
120 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
121}
122
123//OnuIDFromPortNum returns ONUID derived from portNumber
124func OnuIDFromPortNum(portNum uint32) uint32 {
125 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
126}
127
128//IntfIDFromUniPortNum returns IntfID derived from portNum
129func IntfIDFromUniPortNum(portNum uint32) uint32 {
130 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
131}
132
133//UniIDFromPortNum return UniID derived from portNum
134func UniIDFromPortNum(portNum uint32) uint32 {
135 return (portNum) & (MaxUnisPerOnu - 1)
136}
137
138//IntfIDToPortNo returns portId derived from intftype, intfId and portType
139func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
140 if (intfType) == voltha.Port_ETHERNET_NNI {
141 return (1 << nniUniDiffPos) | intfID
142 }
143 if (intfType) == voltha.Port_PON_OLT {
144 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
145 }
146 return 0
147}
148
149//PortNoToIntfID returns portnumber derived from interfaceID
150func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
151 if (intfType) == voltha.Port_ETHERNET_NNI {
152 return (1 << nniUniDiffPos) ^ portno
153 }
154 if (intfType) == voltha.Port_PON_OLT {
155 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
156 }
157 return 0
158}
159
160//IntfIDFromNniPortNum returns Intf ID derived from portNum
161func IntfIDFromNniPortNum(ctx context.Context, portNum uint32) (uint32, error) {
162 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
163 logger.Errorw(ctx, "nniportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
164 return uint32(0), status.Errorf(codes.InvalidArgument, "nni-port-number-out-of-range:%d", portNum)
165 }
166 return (portNum & 0xFFFF), nil
167}
168
169//IntfIDFromPonPortNum returns Intf ID derived from portNum
170func IntfIDFromPonPortNum(ctx context.Context, portNum uint32) (uint32, error) {
171 if portNum < minPonIntfPortNum || portNum > maxPonIntfPortNum {
172 logger.Errorw(ctx, "ponportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
173 return uint32(0), status.Errorf(codes.InvalidArgument, "invalid-pon-port-number:%d", portNum)
174 }
175 return (portNum & 0x7FFF), nil
176}
177
178//IntfIDToPortTypeName returns port type derived from the intfId
179func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
180 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
181 return voltha.Port_PON_OLT
182 }
183 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
184 return voltha.Port_ETHERNET_NNI
185 }
186 return voltha.Port_ETHERNET_UNI
187}
188
189//ExtractAccessFromFlow returns AccessDevice information
190func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
191 if IsUpstream(outPort) {
192 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
193 }
194 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
195}
196
197//IsUpstream returns true for Upstream and false for downstream
198func IsUpstream(outPort uint32) bool {
199 for _, port := range controllerPorts {
200 if port == outPort {
201 return true
202 }
203 }
204 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
205}
206
207//IsControllerBoundFlow returns true/false
208func IsControllerBoundFlow(outPort uint32) bool {
209 for _, port := range controllerPorts {
210 if port == outPort {
211 return true
212 }
213 }
214 return false
215}
216
217//OnuIDFromUniPortNum returns onuId from give portNum information.
218func OnuIDFromUniPortNum(portNum uint32) uint32 {
219 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
220}
221
222//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
223func FlowExtractInfo(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
224 var uniPortNo uint32
225 var ponIntf uint32
226 var onuID uint32
227 var uniID uint32
228 var inPort uint32
229 var ethType uint32
230
231 if flowDirection == upstream {
232 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
233 for _, field := range flows.GetOfbFields(flow) {
234 if field.GetType() == flows.IN_PORT {
235 uniPortNo = field.GetPort()
236 break
237 }
238 }
239 }
240 } else if flowDirection == downstream {
241 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
242 for _, field := range flows.GetOfbFields(flow) {
243 if field.GetType() == flows.METADATA {
244 for _, action := range flows.GetActions(flow) {
245 if action.Type == flows.OUTPUT {
246 if out := action.GetOutput(); out != nil {
247 uniPortNo = out.GetPort()
248 }
249 break
250 }
251 }
252 } else if field.GetType() == flows.IN_PORT {
253 inPort = field.GetPort()
254 } else if field.GetType() == flows.ETH_TYPE {
255 ethType = field.GetEthType()
256 }
257 }
258 }
259 }
260
261 if uniPortNo == 0 {
262 return 0, 0, 0, 0, 0, 0, status.Errorf(codes.NotFound, "uni-not-found-flow-diraction:%s", flowDirection)
263 }
264
265 ponIntf = IntfIDFromUniPortNum(uniPortNo)
266 onuID = OnuIDFromUniPortNum(uniPortNo)
267 uniID = UniIDFromPortNum(uniPortNo)
268
269 logger.Debugw(ctx, "flow-extract-info-result",
270 log.Fields{
271 "uniportno": uniPortNo,
272 "pon-intf": ponIntf,
273 "onu-id": onuID,
274 "uni-id": uniID,
275 "inport": inPort,
276 "ethtype": ethType})
277
278 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
279}