blob: bca05842382a3eb40735994010f03789bee2fd23 [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
17//Package adaptercore provides the utility for olt devices, flows and statistics
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053018package adaptercore
Girish Gowdru0c588b22019-04-23 23:24:56 -040019
20import (
Esin Karamanccb714b2019-11-29 15:02:06 +000021 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
22 "github.com/opencord/voltha-lib-go/v3/pkg/log"
23 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
24 "github.com/opencord/voltha-protos/v3/go/voltha"
Girish Gowdru0c588b22019-04-23 23:24:56 -040025)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053026
27/*=====================================================================
28
Amit Ghoshd4cbe482019-11-21 12:07:14 +000029@TODO: Looks like this Flow id concept below is not used anywhere
30 Propose to remove the below documentation of Flow Id on confirmation
31 of the same
32
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053033Flow id
34
35 Identifies a flow within a single OLT
36 Flow Id is unique per OLT
37 Multiple GEM ports can map to same flow id
38
39 13 11 4 0
40 +--------+--------------+------+
41 | pon id | onu id | Flow |
42 | | | idx |
43 +--------+--------------+------+
44
45 14 bits = 16384 flows (per OLT).
46
47 pon id = 4 bits = 16 PON ports
48 onu id = 7 bits = 128 ONUss per PON port
49 Flow index = 3 bits = 4 bi-directional flows per ONU
50 = 8 uni-directional flows per ONU
51
52
53Logical (OF) UNI port number
54
55 OpenFlow port number corresponding to PON UNI
56
Amit Ghoshd4cbe482019-11-21 12:07:14 +000057 20 12 4 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053058 +--+--------+--------------+------+
Amit Ghoshd4cbe482019-11-21 12:07:14 +000059 |0 | pon id | onu id |uni id|
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053060 +--+--------+--------------+------+
61
Amit Ghoshd4cbe482019-11-21 12:07:14 +000062 pon id = 8 bits = 256 PON ports
63 onu id = 8 bits = 256 ONUs per PON port
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053064
65Logical (OF) NNI port number
66
Amit Ghoshd4cbe482019-11-21 12:07:14 +000067 OpenFlow port number corresponding to PON NNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053068
Amit Ghoshd4cbe482019-11-21 12:07:14 +000069 20 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053070 +--+----------------------------+
71 |1 | intf_id |
72 +--+----------------------------+
73
74 No overlap with UNI port number space
75
76
77PON OLT (OF) port number
78
79 OpenFlow port number corresponding to PON OLT ports
80
Amit Ghoshd4cbe482019-11-21 12:07:14 +000081 31 28 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053082 +--------+------------------------~~~------+
83 | 0x2 | pon intf id |
84 +--------+------------------------~~~------+
85*/
86
Amit Ghoshd4cbe482019-11-21 12:07:14 +000087const (
88 // Number of bits for the physical UNI of the ONUs
89 bitsForUniID = 4
90 // Number of bits for the ONU ID
91 bitsForONUID = 8
92 // Number of bits for PON ID
93 bitsForPONID = 8
94 // Number of bits to differentiate between UNI and NNI Logical Port
95 bitsForUNINNIDiff = 1
96 //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 //Bit position where the differentiation bit is located
103 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
104 //Bit position where the marker for PON port type of OF port is present
105 ponIntfMarkerPos = 28
106 //Value of marker used to distinguish PON port type of OF port
107 ponIntfMarkerValue = 0x2
David K. Bainbridge794735f2020-02-11 21:01:37 -0800108 // Number of bits for NNI ID
109 bitsforNNIID = 20
110 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
111 minNniIntPortNum = (1 << bitsforNNIID)
112 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
113 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000114)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530115
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700116//MinUpstreamPortID value
117var MinUpstreamPortID = 0xfffd
manikkaraj k17652a72019-05-06 09:06:36 -0400118
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700119//MaxUpstreamPortID value
120var MaxUpstreamPortID = 0xfffffffd
121
122var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
123
124//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
125func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000126 var limit = int(onuID)
127 if limit > MaxOnusPerPon {
128 log.Warn("Warning: exceeded the MAX ONUS per PON")
129 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000130 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530131}
132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700133//OnuIDFromPortNum returns ONUID derived from portNumber
134func OnuIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000135 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530136}
137
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138//IntfIDFromUniPortNum returns IntfID derived from portNum
139func IntfIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000140 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530141}
142
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700143//UniIDFromPortNum return UniID derived from portNum
144func UniIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000145 return (portNum) & (MaxUnisPerOnu - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530146}
147
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700148//IntfIDToPortNo returns portId derived from intftype, intfId and portType
149func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400150 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000151 return (1 << nniUniDiffPos) | intfID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530152 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000154 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700155 }
156 return 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530157}
158
Naga Manjunath7615e552019-10-11 22:35:47 +0530159//PortNoToIntfID returns portnumber derived from interfaceID
160func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
161 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000162 return (1 << nniUniDiffPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530163 }
164 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000165 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530166 }
167 return 0
168}
169
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700170//IntfIDFromNniPortNum returns Intf ID derived from portNum
David K. Bainbridge794735f2020-02-11 21:01:37 -0800171func IntfIDFromNniPortNum(portNum uint32) (uint32, error) {
172 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
173 log.Errorw("NNIPortNumber is not in valid range", log.Fields{"portNum": portNum})
174 return uint32(0), ErrInvalidPortRange
175 }
176 return (portNum & 0xFFFF), nil
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530177}
178
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179//IntfIDToPortTypeName returns port type derived from the intfId
180func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000181 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530182 return voltha.Port_PON_OLT
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530183 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000184 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 return voltha.Port_ETHERNET_NNI
186 }
187 return voltha.Port_ETHERNET_UNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530188}
189
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190//ExtractAccessFromFlow returns AccessDevice information
191func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400192 if IsUpstream(outPort) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530194 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700195 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530196}
197
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700198//IsUpstream returns true for Upstream and false for downstream
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530199func IsUpstream(outPort uint32) bool {
manikkaraj k17652a72019-05-06 09:06:36 -0400200 for _, port := range controllerPorts {
201 if port == outPort {
202 return true
203 }
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530204 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000205 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530206}
manikkaraj k17652a72019-05-06 09:06:36 -0400207
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700208//IsControllerBoundFlow returns true/false
manikkaraj k17652a72019-05-06 09:06:36 -0400209func IsControllerBoundFlow(outPort uint32) bool {
210 for _, port := range controllerPorts {
211 if port == outPort {
212 return true
213 }
214 }
215 return false
216}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400217
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700218//OnuIDFromUniPortNum returns onuId from give portNum information.
219func OnuIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000220 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400221}
222
Humera Kouser94d7a842019-08-25 19:04:32 -0400223//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
224func FlowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225 var uniPortNo uint32
226 var ponIntf uint32
227 var onuID uint32
228 var uniID uint32
Humera Kouser94d7a842019-08-25 19:04:32 -0400229 var inPort uint32
230 var ethType uint32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400231
232 if flowDirection == "upstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700233 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
234 for _, field := range flows.GetOfbFields(flow) {
235 if field.GetType() == flows.IN_PORT {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400236 uniPortNo = field.GetPort()
237 break
238 }
239 }
240 }
241 } else if flowDirection == "downstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700242 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
243 for _, field := range flows.GetOfbFields(flow) {
244 if field.GetType() == flows.METADATA {
245 for _, action := range flows.GetActions(flow) {
246 if action.Type == flows.OUTPUT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400247 if out := action.GetOutput(); out != nil {
248 uniPortNo = out.GetPort()
249 }
250 break
251 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400252 }
Scott Baker355d1742019-10-24 10:57:52 -0700253 } else if field.GetType() == flows.IN_PORT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400254 inPort = field.GetPort()
Scott Baker355d1742019-10-24 10:57:52 -0700255 } else if field.GetType() == flows.ETH_TYPE {
Humera Kouser94d7a842019-08-25 19:04:32 -0400256 ethType = field.GetEthType()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400257 }
258 }
259 }
260 }
261
262 if uniPortNo == 0 {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800263 return 0, 0, 0, 0, 0, 0, NewErrNotFound("pon-interface", log.Fields{
264 "flow-direction": flowDirection}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400265 }
266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700267 ponIntf = IntfIDFromUniPortNum(uniPortNo)
268 onuID = OnuIDFromUniPortNum(uniPortNo)
269 uniID = UniIDFromPortNum(uniPortNo)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400270
Girish Gowdra3d633032019-12-10 16:37:05 +0530271 log.Debugw("flow extract info result",
272 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
273 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
274
Humera Kouser94d7a842019-08-25 19:04:32 -0400275 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400276}