blob: efc00291266b9c20c3047c091af6841a89edbc31 [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 (
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040021 "errors"
Amit Ghoshd4cbe482019-11-21 12:07:14 +000022
Esin Karamanccb714b2019-11-29 15:02:06 +000023 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
24 "github.com/opencord/voltha-lib-go/v3/pkg/log"
25 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
26 "github.com/opencord/voltha-protos/v3/go/voltha"
Girish Gowdru0c588b22019-04-23 23:24:56 -040027)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053028
29/*=====================================================================
30
Amit Ghoshd4cbe482019-11-21 12:07:14 +000031@TODO: Looks like this Flow id concept below is not used anywhere
32 Propose to remove the below documentation of Flow Id on confirmation
33 of the same
34
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053035Flow id
36
37 Identifies a flow within a single OLT
38 Flow Id is unique per OLT
39 Multiple GEM ports can map to same flow id
40
41 13 11 4 0
42 +--------+--------------+------+
43 | pon id | onu id | Flow |
44 | | | idx |
45 +--------+--------------+------+
46
47 14 bits = 16384 flows (per OLT).
48
49 pon id = 4 bits = 16 PON ports
50 onu id = 7 bits = 128 ONUss per PON port
51 Flow index = 3 bits = 4 bi-directional flows per ONU
52 = 8 uni-directional flows per ONU
53
54
55Logical (OF) UNI port number
56
57 OpenFlow port number corresponding to PON UNI
58
Amit Ghoshd4cbe482019-11-21 12:07:14 +000059 20 12 4 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053060 +--+--------+--------------+------+
Amit Ghoshd4cbe482019-11-21 12:07:14 +000061 |0 | pon id | onu id |uni id|
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053062 +--+--------+--------------+------+
63
Amit Ghoshd4cbe482019-11-21 12:07:14 +000064 pon id = 8 bits = 256 PON ports
65 onu id = 8 bits = 256 ONUs per PON port
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053066
67Logical (OF) NNI port number
68
Amit Ghoshd4cbe482019-11-21 12:07:14 +000069 OpenFlow port number corresponding to PON NNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053070
Amit Ghoshd4cbe482019-11-21 12:07:14 +000071 20 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053072 +--+----------------------------+
73 |1 | intf_id |
74 +--+----------------------------+
75
76 No overlap with UNI port number space
77
78
79PON OLT (OF) port number
80
81 OpenFlow port number corresponding to PON OLT ports
82
Amit Ghoshd4cbe482019-11-21 12:07:14 +000083 31 28 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +053084 +--------+------------------------~~~------+
85 | 0x2 | pon intf id |
86 +--------+------------------------~~~------+
87*/
88
Amit Ghoshd4cbe482019-11-21 12:07:14 +000089const (
90 // Number of bits for the physical UNI of the ONUs
91 bitsForUniID = 4
92 // Number of bits for the ONU ID
93 bitsForONUID = 8
94 // Number of bits for PON ID
95 bitsForPONID = 8
96 // Number of bits to differentiate between UNI and NNI Logical Port
97 bitsForUNINNIDiff = 1
98 //MaxOnusPerPon is Max number of ONUs on any PON port
99 MaxOnusPerPon = (1 << bitsForONUID)
100 //MaxPonsPerOlt is Max number of PON ports on any OLT
101 MaxPonsPerOlt = (1 << bitsForPONID)
102 //MaxUnisPerOnu is the Max number of UNI ports on any ONU
103 MaxUnisPerOnu = (1 << bitsForUniID)
104 //Bit position where the differentiation bit is located
105 nniUniDiffPos = (bitsForUniID + bitsForONUID + bitsForPONID)
106 //Bit position where the marker for PON port type of OF port is present
107 ponIntfMarkerPos = 28
108 //Value of marker used to distinguish PON port type of OF port
109 ponIntfMarkerValue = 0x2
110)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530111
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112//MinUpstreamPortID value
113var MinUpstreamPortID = 0xfffd
manikkaraj k17652a72019-05-06 09:06:36 -0400114
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115//MaxUpstreamPortID value
116var MaxUpstreamPortID = 0xfffffffd
117
118var controllerPorts = []uint32{0xfffd, 0x7ffffffd, 0xfffffffd}
119
120//MkUniPortNum returns new UNIportNum based on intfID, inuID and uniID
121func MkUniPortNum(intfID, onuID, uniID uint32) uint32 {
gerardo.laurenzi72c84382019-07-11 15:03:46 +0000122 var limit = int(onuID)
123 if limit > MaxOnusPerPon {
124 log.Warn("Warning: exceeded the MAX ONUS per PON")
125 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000126 return (intfID << (bitsForUniID + bitsForONUID)) | (onuID << bitsForUniID) | uniID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530127}
128
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700129//OnuIDFromPortNum returns ONUID derived from portNumber
130func OnuIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000131 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530132}
133
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134//IntfIDFromUniPortNum returns IntfID derived from portNum
135func IntfIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000136 return (portNum >> (bitsForUniID + bitsForONUID)) & (MaxPonsPerOlt - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530137}
138
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700139//UniIDFromPortNum return UniID derived from portNum
140func UniIDFromPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000141 return (portNum) & (MaxUnisPerOnu - 1)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530142}
143
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700144//IntfIDToPortNo returns portId derived from intftype, intfId and portType
145func IntfIDToPortNo(intfID uint32, intfType voltha.Port_PortType) uint32 {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400146 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000147 return (1 << nniUniDiffPos) | intfID
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530148 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700149 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000150 return (ponIntfMarkerValue << ponIntfMarkerPos) | intfID
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700151 }
152 return 0
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530153}
154
Naga Manjunath7615e552019-10-11 22:35:47 +0530155//PortNoToIntfID returns portnumber derived from interfaceID
156func PortNoToIntfID(portno uint32, intfType voltha.Port_PortType) uint32 {
157 if (intfType) == voltha.Port_ETHERNET_NNI {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000158 return (1 << nniUniDiffPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530159 }
160 if (intfType) == voltha.Port_PON_OLT {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000161 return (ponIntfMarkerValue << ponIntfMarkerPos) ^ portno
Naga Manjunath7615e552019-10-11 22:35:47 +0530162 }
163 return 0
164}
165
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700166//IntfIDFromNniPortNum returns Intf ID derived from portNum
167func IntfIDFromNniPortNum(portNum uint32) uint32 {
168 return portNum & 0xFFFF
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530169}
170
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700171//IntfIDToPortTypeName returns port type derived from the intfId
172func IntfIDToPortTypeName(intfID uint32) voltha.Port_PortType {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000173 if ((ponIntfMarkerValue << ponIntfMarkerPos) ^ intfID) < MaxPonsPerOlt {
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530174 return voltha.Port_PON_OLT
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530175 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000176 if (intfID & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700177 return voltha.Port_ETHERNET_NNI
178 }
179 return voltha.Port_ETHERNET_UNI
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530180}
181
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700182//ExtractAccessFromFlow returns AccessDevice information
183func ExtractAccessFromFlow(inPort, outPort uint32) (uint32, uint32, uint32, uint32) {
Girish Gowdru0c588b22019-04-23 23:24:56 -0400184 if IsUpstream(outPort) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700185 return inPort, IntfIDFromUniPortNum(inPort), OnuIDFromPortNum(inPort), UniIDFromPortNum(inPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530186 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700187 return outPort, IntfIDFromUniPortNum(outPort), OnuIDFromPortNum(outPort), UniIDFromPortNum(outPort)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530188}
189
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700190//IsUpstream returns true for Upstream and false for downstream
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530191func IsUpstream(outPort uint32) bool {
manikkaraj k17652a72019-05-06 09:06:36 -0400192 for _, port := range controllerPorts {
193 if port == outPort {
194 return true
195 }
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530196 }
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000197 return (outPort & (1 << nniUniDiffPos)) == (1 << nniUniDiffPos)
Manjunath Vanaraj39ecd412019-03-15 20:05:41 +0530198}
manikkaraj k17652a72019-05-06 09:06:36 -0400199
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700200//IsControllerBoundFlow returns true/false
manikkaraj k17652a72019-05-06 09:06:36 -0400201func IsControllerBoundFlow(outPort uint32) bool {
202 for _, port := range controllerPorts {
203 if port == outPort {
204 return true
205 }
206 }
207 return false
208}
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210//OnuIDFromUniPortNum returns onuId from give portNum information.
211func OnuIDFromUniPortNum(portNum uint32) uint32 {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000212 return (portNum >> bitsForUniID) & (MaxOnusPerPon - 1)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400213}
214
Humera Kouser94d7a842019-08-25 19:04:32 -0400215//FlowExtractInfo fetches uniport from the flow, based on which it gets and returns ponInf, onuID, uniID, inPort and ethType
216func FlowExtractInfo(flow *ofp.OfpFlowStats, flowDirection string) (uint32, uint32, uint32, uint32, uint32, uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217 var uniPortNo uint32
218 var ponIntf uint32
219 var onuID uint32
220 var uniID uint32
Humera Kouser94d7a842019-08-25 19:04:32 -0400221 var inPort uint32
222 var ethType uint32
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400223
224 if flowDirection == "upstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700225 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
226 for _, field := range flows.GetOfbFields(flow) {
227 if field.GetType() == flows.IN_PORT {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400228 uniPortNo = field.GetPort()
229 break
230 }
231 }
232 }
233 } else if flowDirection == "downstream" {
Scott Baker355d1742019-10-24 10:57:52 -0700234 if uniPortNo = flows.GetChildPortFromTunnelId(flow); uniPortNo == 0 {
235 for _, field := range flows.GetOfbFields(flow) {
236 if field.GetType() == flows.METADATA {
237 for _, action := range flows.GetActions(flow) {
238 if action.Type == flows.OUTPUT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400239 if out := action.GetOutput(); out != nil {
240 uniPortNo = out.GetPort()
241 }
242 break
243 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400244 }
Scott Baker355d1742019-10-24 10:57:52 -0700245 } else if field.GetType() == flows.IN_PORT {
Humera Kouser94d7a842019-08-25 19:04:32 -0400246 inPort = field.GetPort()
Scott Baker355d1742019-10-24 10:57:52 -0700247 } else if field.GetType() == flows.ETH_TYPE {
Humera Kouser94d7a842019-08-25 19:04:32 -0400248 ethType = field.GetEthType()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400249 }
250 }
251 }
252 }
253
254 if uniPortNo == 0 {
Humera Kouser94d7a842019-08-25 19:04:32 -0400255 return 0, 0, 0, 0, 0, 0, errors.New("failed to extract Pon Interface, ONU Id and Uni Id from flow")
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400256 }
257
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700258 ponIntf = IntfIDFromUniPortNum(uniPortNo)
259 onuID = OnuIDFromUniPortNum(uniPortNo)
260 uniID = UniIDFromPortNum(uniPortNo)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400261
Girish Gowdra3d633032019-12-10 16:37:05 +0530262 log.Debugw("flow extract info result",
263 log.Fields{"uniPortNo": uniPortNo, "ponIntf": ponIntf,
264 "onuID": onuID, "uniID": uniID, "inPort": inPort, "ethType": ethType})
265
Humera Kouser94d7a842019-08-25 19:04:32 -0400266 return uniPortNo, ponIntf, onuID, uniID, inPort, ethType, nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400267}