blob: 9526ee7b5c5700e63f5100db20826e51fa4f89c2 [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
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
Girish Gowdru0c588b22019-04-23 23:24:56 -040019
20import (
Neha Sharma96b7bf22020-06-15 10:37:32 +000021 "context"
Kent Hagermane6ff1012020-07-14 15:07:53 -040022
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070023 "github.com/opencord/voltha-lib-go/v5/pkg/flows"
24 "github.com/opencord/voltha-lib-go/v5/pkg/log"
Thomas Lee S94109f12020-03-03 16:39:29 +053025 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070026 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
27 "github.com/opencord/voltha-protos/v4/go/voltha"
Girish Gowdru0c588b22019-04-23 23:24:56 -040028)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053029
30/*=====================================================================
31
Amit Ghoshd4cbe482019-11-21 12:07:14 +000032@TODO: Looks like this Flow id concept below is not used anywhere
33 Propose to remove the below documentation of Flow Id on confirmation
34 of the same
35
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053036Flow id
37
38 Identifies a flow within a single OLT
39 Flow Id is unique per OLT
40 Multiple GEM ports can map to same flow id
41
42 13 11 4 0
43 +--------+--------------+------+
44 | pon id | onu id | Flow |
45 | | | idx |
46 +--------+--------------+------+
47
48 14 bits = 16384 flows (per OLT).
49
50 pon id = 4 bits = 16 PON ports
51 onu id = 7 bits = 128 ONUss per PON port
52 Flow index = 3 bits = 4 bi-directional flows per ONU
53 = 8 uni-directional flows per ONU
54
55
56Logical (OF) UNI port number
57
58 OpenFlow port number corresponding to PON UNI
59
Amit Ghoshd4cbe482019-11-21 12:07:14 +000060 20 12 4 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053061 +--+--------+--------------+------+
Amit Ghoshd4cbe482019-11-21 12:07:14 +000062 |0 | pon id | onu id |uni id|
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053063 +--+--------+--------------+------+
64
Amit Ghoshd4cbe482019-11-21 12:07:14 +000065 pon id = 8 bits = 256 PON ports
66 onu id = 8 bits = 256 ONUs per PON port
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053067
68Logical (OF) NNI port number
69
Amit Ghoshd4cbe482019-11-21 12:07:14 +000070 OpenFlow port number corresponding to PON NNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053071
Amit Ghoshd4cbe482019-11-21 12:07:14 +000072 20 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053073 +--+----------------------------+
74 |1 | intf_id |
75 +--+----------------------------+
76
77 No overlap with UNI port number space
78
79
80PON OLT (OF) port number
81
82 OpenFlow port number corresponding to PON OLT ports
83
Amit Ghoshd4cbe482019-11-21 12:07:14 +000084 31 28 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053085 +--------+------------------------~~~------+
86 | 0x2 | pon intf id |
87 +--------+------------------------~~~------+
88*/
89
Amit Ghoshd4cbe482019-11-21 12:07:14 +000090const (
91 // Number of bits for the physical UNI of the ONUs
92 bitsForUniID = 4
93 // Number of bits for the ONU ID
94 bitsForONUID = 8
95 // Number of bits for PON ID
96 bitsForPONID = 8
Kent Hagermane6ff1012020-07-14 15:07:53 -040097 // MaxOnusPerPon is Max number of ONUs on any PON port
Amit Ghoshd4cbe482019-11-21 12:07:14 +000098 MaxOnusPerPon = (1 << bitsForONUID)
Kent Hagermane6ff1012020-07-14 15:07:53 -040099 // MaxPonsPerOlt is Max number of PON ports on any OLT
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000100 MaxPonsPerOlt = (1 << bitsForPONID)
Kent Hagermane6ff1012020-07-14 15:07:53 -0400101 // MaxUnisPerOnu is the Max number of UNI ports on any ONU
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000102 MaxUnisPerOnu = (1 << bitsForUniID)
Kent Hagermane6ff1012020-07-14 15:07:53 -0400103 // Bit position where the differentiation bit is located
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000104 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
Kent Hagermane6ff1012020-07-14 15:07:53 -0400105 // Bit position where the marker for PON port type of OF port is present
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000106 ponIntfMarkerPos = 28
Kent Hagermane6ff1012020-07-14 15:07:53 -0400107 // Value of marker used to distinguish PON port type of OF port
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000108 ponIntfMarkerValue = 0x2
David K. Bainbridge794735f2020-02-11 21:01:37 -0800109 // Number of bits for NNI ID
110 bitsforNNIID = 20
111 // minNniIntPortNum is used to store start range of nni port number (1 << 20) 1048576
112 minNniIntPortNum = (1 << bitsforNNIID)
113 // maxNniPortNum is used to store the maximum range of nni port number ((1 << 21)-1) 2097151
114 maxNniPortNum = ((1 << (bitsforNNIID + 1)) - 1)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700115 // minPonIntfPortNum stores the minimum pon port number
116 minPonIntfPortNum = ponIntfMarkerValue << ponIntfMarkerPos
117 // maxPonIntfPortNum stores the maximum pon port number
118 maxPonIntfPortNum = (ponIntfMarkerValue << ponIntfMarkerPos) | (2 ^ bitsForPONID - 1)
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000119)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530120
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121//MinUpstreamPortID value
122var MinUpstreamPortID = 0xfffd
manikkaraj k17652a72019-05-06 09:06:36 -0400123
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700124//MaxUpstreamPortID value
125var MaxUpstreamPortID = 0xfffffffd
126
127var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
128
129//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
Neha Sharma96b7bf22020-06-15 10:37:32 +0000130func MkUniPortNum(ctx context.Context, intfID, onuID, uniID uint32) uint32 {
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000131 var limit = int(onuID)
132 if limit > MaxOnusPerPon {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000133 logger.Warn(ctx, "exceeded-the-max-onus-per-pon")
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000134 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000135 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530136}
137
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138//OnuIDFromPortNum returns ONUID derived from portNumber
139func OnuIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000140 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530141}
142
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700143//IntfIDFromUniPortNum returns IntfID derived from portNum
144func IntfIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000145 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530146}
147
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700148//UniIDFromPortNum return UniID derived from portNum
149func UniIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000150 return (portNum) & (MaxUnisPerOnu - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530151}
152
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700153//IntfIDToPortNo returns portId derived from intftype, intfId and portType
154func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400155 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000156 return (1 << nniUniDiffPos) | intfID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530157 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700158 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000159 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700160 }
161 return 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530162}
163
Naga Manjunath7615e552019-10-11 22:35:47 +0530164//PortNoToIntfID returns portnumber derived from interfaceID
165func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
166 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000167 return (1 << nniUniDiffPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530168 }
169 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000170 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530171 }
172 return 0
173}
174
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700175//IntfIDFromNniPortNum returns Intf ID derived from portNum
Neha Sharma96b7bf22020-06-15 10:37:32 +0000176func IntfIDFromNniPortNum(ctx context.Context, portNum uint32) (uint32, error) {
David K. Bainbridge794735f2020-02-11 21:01:37 -0800177 if portNum < minNniIntPortNum || portNum > maxNniPortNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000178 logger.Errorw(ctx, "nniportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
Thomas Lee S94109f12020-03-03 16:39:29 +0530179 return uint32(0), olterrors.ErrInvalidPortRange
David K. Bainbridge794735f2020-02-11 21:01:37 -0800180 }
181 return (portNum & 0xFFFF), nil
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530182}
183
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700184//IntfIDFromPonPortNum returns Intf ID derived from portNum
185func IntfIDFromPonPortNum(ctx context.Context, portNum uint32) (uint32, error) {
186 if portNum < minPonIntfPortNum || portNum > maxPonIntfPortNum {
187 logger.Errorw(ctx, "ponportnumber-is-not-in-valid-range", log.Fields{"portnum": portNum})
188 return uint32(0), olterrors.ErrInvalidPortRange
189 }
190 return (portNum & 0x7FFF), nil
191}
192
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193//IntfIDToPortTypeName returns port type derived from the intfId
194func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000195 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530196 return voltha.Port_PON_OLT
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530197 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000198 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199 return voltha.Port_ETHERNET_NNI
200 }
201 return voltha.Port_ETHERNET_UNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530202}
203
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700204//ExtractAccessFromFlow returns AccessDevice information
205func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400206 if IsUpstream(outPort) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700207 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530208 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//IsUpstream returns true for Upstream and false for downstream
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530213func IsUpstream(outPort uint32) bool {
manikkaraj k17652a72019-05-06 09:06:36 -0400214 for _, port := range controllerPorts {
215 if port == outPort {
216 return true
217 }
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530218 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000219 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530220}
manikkaraj k17652a72019-05-06 09:06:36 -0400221
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700222//IsControllerBoundFlow returns true/false
manikkaraj k17652a72019-05-06 09:06:36 -0400223func IsControllerBoundFlow(outPort uint32) bool {
224 for _, port := range controllerPorts {
225 if port == outPort {
226 return true
227 }
228 }
229 return false
230}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400231
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700232//OnuIDFromUniPortNum returns onuId from give portNum information.
233func OnuIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000234 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400235}
236
Humera Kouser94d7a842019-08-25 19:04:32 -0400237//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 +0000238func FlowExtractInfo(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700239 var uniPortNo uint32
240 var ponIntf uint32
241 var onuID uint32
242 var uniID uint32
Humera Kouser94d7a842019-08-25 19:04:32 -0400243 var inPort uint32
244 var ethType uint32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400245
246 if flowDirection == "upstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700247 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
248 for _, field := range flows.GetOfbFields(flow) {
249 if field.GetType() == flows.IN_PORT {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400250 uniPortNo = field.GetPort()
251 break
252 }
253 }
254 }
255 } else if flowDirection == "downstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700256 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
257 for _, field := range flows.GetOfbFields(flow) {
258 if field.GetType() == flows.METADATA {
259 for _, action := range flows.GetActions(flow) {
260 if action.Type == flows.OUTPUT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400261 if out := action.GetOutput(); out != nil {
262 uniPortNo = out.GetPort()
263 }
264 break
265 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400266 }
Scott Baker355d1742019-10-24 10:57:52 -0700267 } else if field.GetType() == flows.IN_PORT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400268 inPort = field.GetPort()
Scott Baker355d1742019-10-24 10:57:52 -0700269 } else if field.GetType() == flows.ETH_TYPE {
Humera Kouser94d7a842019-08-25 19:04:32 -0400270 ethType = field.GetEthType()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400271 }
272 }
273 }
274 }
275
276 if uniPortNo == 0 {
Shrey Baid26912972020-04-16 21:02:31 +0530277 return 0, 0, 0, 0, 0, 0, olterrors.NewErrNotFound("pon-interface", log.Fields{"flow-direction": flowDirection}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400278 }
279
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700280 ponIntf = IntfIDFromUniPortNum(uniPortNo)
281 onuID = OnuIDFromUniPortNum(uniPortNo)
282 uniID = UniIDFromPortNum(uniPortNo)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400283
Neha Sharma96b7bf22020-06-15 10:37:32 +0000284 logger.Debugw(ctx, "flow-extract-info-result",
Shrey Baid26912972020-04-16 21:02:31 +0530285 log.Fields{
286 "uniportno": uniPortNo,
287 "pon-intf": ponIntf,
288 "onu-id": onuID,
289 "uni-id": uniID,
290 "inport": inPort,
291 "ethtype": ethType})
Girish Gowdra3d633032019-12-10 16:37:05 +0530292
Humera Kouser94d7a842019-08-25 19:04:32 -0400293 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400294}