blob: 688ccd8bf26c7011b1789a9cde092f89818b2dbe [file] [log] [blame]
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +05301/*
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 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070016
Mahir Gunyel85f61c12021-10-06 11:53:45 -070017package platform
Girish Gowdru0c588b22019-04-23 23:24:56 -040018
19import (
Neha Sharma96b7bf22020-06-15 10:37:32 +000020 "context"
Kent Hagermane6ff1012020-07-14 15:07:53 -040021
khenaidoo106c61a2021-08-11 18:05:46 -040022 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
23 "github.com/opencord/voltha-lib-go/v7/pkg/log"
khenaidoo106c61a2021-08-11 18:05:46 -040024 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
25 "github.com/opencord/voltha-protos/v5/go/voltha"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070026 "google.golang.org/grpc/codes"
27 "google.golang.org/grpc/status"
Girish Gowdru0c588b22019-04-23 23:24:56 -040028)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053029
30/*=====================================================================
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053031Logical (OF) UNI port number
32
33 OpenFlow port number corresponding to PON UNI
34
Mahir Gunyel0c009fc2021-10-22 17:47:16 -070035 24 16 8 0
36 +--+--------+----------+----------+
37 |0 | pon id | onu id | uni id |
38 +--+--------+----------+----------+
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053039
Amit Ghoshd4cbe482019-11-21 12:07:14 +000040 pon id = 8 bits = 256 PON ports
41 onu id = 8 bits = 256 ONUs per PON port
Mahir Gunyel0c009fc2021-10-22 17:47:16 -070042 uni id = 8 bits = 256 UNIs per ONU
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053043
44Logical (OF) NNI port number
45
Amit Ghoshd4cbe482019-11-21 12:07:14 +000046 OpenFlow port number corresponding to PON NNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053047
Mahir Gunyel0c009fc2021-10-22 17:47:16 -070048 24 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053049 +--+----------------------------+
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
Amit Ghoshd4cbe482019-11-21 12:07:14 +000060 31 28 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053061 +--------+------------------------~~~------+
62 | 0x2 | pon intf id |
63 +--------+------------------------~~~------+
64*/
65
Amit Ghoshd4cbe482019-11-21 12:07:14 +000066const (
67 // Number of bits for the physical UNI of the ONUs
Mahir Gunyel0c009fc2021-10-22 17:47:16 -070068 bitsForUniID = 8
Amit Ghoshd4cbe482019-11-21 12:07:14 +000069 // Number of bits for the ONU ID
70 bitsForONUID = 8
71 // Number of bits for PON ID
72 bitsForPONID = 8
Kent Hagermane6ff1012020-07-14 15:07:53 -040073 // MaxOnusPerPon is Max number of ONUs on any PON port
Amit Ghoshd4cbe482019-11-21 12:07:14 +000074 MaxOnusPerPon = (1 << bitsForONUID)
Kent Hagermane6ff1012020-07-14 15:07:53 -040075 // MaxPonsPerOlt is Max number of PON ports on any OLT
Amit Ghoshd4cbe482019-11-21 12:07:14 +000076 MaxPonsPerOlt = (1 << bitsForPONID)
Kent Hagermane6ff1012020-07-14 15:07:53 -040077 // MaxUnisPerOnu is the Max number of UNI ports on any ONU
Amit Ghoshd4cbe482019-11-21 12:07:14 +000078 MaxUnisPerOnu = (1 << bitsForUniID)
Kent Hagermane6ff1012020-07-14 15:07:53 -040079 // Bit position where the differentiation bit is located
Amit Ghoshd4cbe482019-11-21 12:07:14 +000080 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
Kent Hagermane6ff1012020-07-14 15:07:53 -040081 // Bit position where the marker for PON port type of OF port is present
Amit Ghoshd4cbe482019-11-21 12:07:14 +000082 ponIntfMarkerPos = 28
Kent Hagermane6ff1012020-07-14 15:07:53 -040083 // Value of marker used to distinguish PON port type of OF port
Amit Ghoshd4cbe482019-11-21 12:07:14 +000084 ponIntfMarkerValue = 0x2
Mahir Gunyel0c009fc2021-10-22 17:47:16 -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)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070090 minPonIntfPortNum = ponIntfMarkerValue << ponIntfMarkerPos
Mahir Gunyel0c009fc2021-10-22 17:47:16 -070091 // maxPonIntfPortNum stores the maximum pon port number (536871167)
92 maxPonIntfPortNum = ((ponIntfMarkerValue << ponIntfMarkerPos) | (1 << bitsForPONID)) - 1
Mahir Gunyel85f61c12021-10-06 11:53:45 -070093 upstream = "upstream"
94 downstream = "downstream"
Mahir Gunyel0c009fc2021-10-22 17:47:16 -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
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000101)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530102
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700103var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
104
105//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
Neha Sharma96b7bf22020-06-15 10:37:32 +0000106func MkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
Mahir Gunyel0c009fc2021-10-22 17:47:16 -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)
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000112 if limit > MaxOnusPerPon {
Mahir Gunyel0c009fc2021-10-22 17:47:16 -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")
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000118 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000119 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530120}
121
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700122//OnuIDFromPortNum returns ONUID derived from portNumber
123func OnuIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000124 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530125}
126
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700127//IntfIDFromUniPortNum returns IntfID derived from portNum
128func IntfIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000129 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530130}
131
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700132//UniIDFromPortNum return UniID derived from portNum
133func UniIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000134 return (portNum) & (MaxUnisPerOnu - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530135}
136
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700137//IntfIDToPortNo returns portId derived from intftype, intfId and portType
138func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400139 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000140 return (1 << nniUniDiffPos) | intfID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530141 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700142 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000143 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700144 }
145 return 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530146}
147
Naga Manjunath7615e552019-10-11 22:35:47 +0530148//PortNoToIntfID returns portnumber derived from interfaceID
149func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
150 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000151 return (1 << nniUniDiffPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530152 }
153 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000154 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530155 }
156 return 0
157}
158
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700159//IntfIDFromNniPortNum returns Intf ID derived from portNum
Neha Sharma96b7bf22020-06-15 10:37:32 +0000160func IntfIDFromNniPortNum(ctx context.Context, portNum uint32) (uint32, error) {
Mahir Gunyel0c009fc2021-10-22 17:47:16 -0700161 if portNum < minNniPortNum || portNum > maxNniPortNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000162 logger.Errorw(ctx, "nniportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700163 return uint32(0), status.Errorf(codes.InvalidArgument, "nni-port-number-out-of-range:%d", portNum)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800164 }
Mahir Gunyel0c009fc2021-10-22 17:47:16 -0700165 return (portNum & (minNniPortNum - 1)), nil
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530166}
167
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700168//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})
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700172 return uint32(0), status.Errorf(codes.InvalidArgument, "invalid-pon-port-number:%d", portNum)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700173 }
Mahir Gunyel0c009fc2021-10-22 17:47:16 -0700174 return (portNum & ((1 << ponIntfMarkerPos) - 1)), nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700175}
176
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700177//IntfIDToPortTypeName returns port type derived from the intfId
178func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000179 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530180 return voltha.Port_PON_OLT
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530181 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000182 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700183 return voltha.Port_ETHERNET_NNI
184 }
185 return voltha.Port_ETHERNET_UNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530186}
187
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700188//ExtractAccessFromFlow returns AccessDevice information
189func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400190 if IsUpstream(outPort) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700191 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530192 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530194}
195
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700196//IsUpstream returns true for Upstream and false for downstream
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530197func IsUpstream(outPort uint32) bool {
manikkaraj k17652a72019-05-06 09:06:36 -0400198 for _, port := range controllerPorts {
199 if port == outPort {
200 return true
201 }
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530202 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000203 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530204}
manikkaraj k17652a72019-05-06 09:06:36 -0400205
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700206//IsControllerBoundFlow returns true/false
manikkaraj k17652a72019-05-06 09:06:36 -0400207func IsControllerBoundFlow(outPort uint32) bool {
208 for _, port := range controllerPorts {
209 if port == outPort {
210 return true
211 }
212 }
213 return false
214}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400215
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700216//OnuIDFromUniPortNum returns onuId from give portNum information.
217func OnuIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000218 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400219}
220
Humera Kouser94d7a842019-08-25 19:04:32 -0400221//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
Neha Sharma96b7bf22020-06-15 10:37:32 +0000222func FlowExtractInfo(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700223 var uniPortNo uint32
224 var ponIntf uint32
225 var onuID uint32
226 var uniID uint32
Humera Kouser94d7a842019-08-25 19:04:32 -0400227 var inPort uint32
228 var ethType uint32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400229
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700230 if flowDirection == upstream {
Scott Baker355d1742019-10-24 10:57:52 -0700231 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
232 for _, field := range flows.GetOfbFields(flow) {
233 if field.GetType() == flows.IN_PORT {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400234 uniPortNo = field.GetPort()
235 break
236 }
237 }
238 }
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700239 } else if flowDirection == downstream {
Scott Baker355d1742019-10-24 10:57:52 -0700240 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 {
Humera Kouser94d7a842019-08-25 19:04:32 -0400245 if out := action.GetOutput(); out != nil {
246 uniPortNo = out.GetPort()
247 }
248 break
249 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400250 }
Scott Baker355d1742019-10-24 10:57:52 -0700251 } else if field.GetType() == flows.IN_PORT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400252 inPort = field.GetPort()
Scott Baker355d1742019-10-24 10:57:52 -0700253 } else if field.GetType() == flows.ETH_TYPE {
Humera Kouser94d7a842019-08-25 19:04:32 -0400254 ethType = field.GetEthType()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400255 }
256 }
257 }
258 }
259
260 if uniPortNo == 0 {
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700261 return 0, 0, 0, 0, 0, 0, status.Errorf(codes.NotFound, "uni-not-found-flow-diraction:%s", flowDirection)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400262 }
263
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700264 ponIntf = IntfIDFromUniPortNum(uniPortNo)
265 onuID = OnuIDFromUniPortNum(uniPortNo)
266 uniID = UniIDFromPortNum(uniPortNo)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400267
Neha Sharma96b7bf22020-06-15 10:37:32 +0000268 logger.Debugw(ctx, "flow-extract-info-result",
Shrey Baid26912972020-04-16 21:02:31 +0530269 log.Fields{
270 "uniportno": uniPortNo,
271 "pon-intf": ponIntf,
272 "onu-id": onuID,
273 "uni-id": uniID,
274 "inport": inPort,
275 "ethtype": ethType})
Girish Gowdra3d633032019-12-10 16:37:05 +0530276
Humera Kouser94d7a842019-08-25 19:04:32 -0400277 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400278}