blob: b31c312fe7c5288146f4fd88f852b0aec416cf80 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +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 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
22 "crypto/md5"
Matteo Scandolo6056e822019-11-13 14:05:29 -080023 "encoding/hex"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "encoding/json"
Girish Gowdracefae192020-03-19 18:14:10 -070025 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053026 "fmt"
Manikkaraj kb1d51442019-07-23 10:41:02 -040027 "math/big"
Girish Gowdrafae935c2020-02-17 19:21:44 +053028 "strings"
William Kurkian740a09c2019-10-23 17:07:38 -040029 "sync"
Girish Gowdra3d633032019-12-10 16:37:05 +053030 "time"
Manikkaraj kb1d51442019-07-23 10:41:02 -040031
Esin Karamanccb714b2019-11-29 15:02:06 +000032 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v3/pkg/log"
34 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080035 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000036 "github.com/opencord/voltha-protos/v3/go/common"
37 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
38 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
39 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
40 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
41 "github.com/opencord/voltha-protos/v3/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040042
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040043 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053044 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053045 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000046 "google.golang.org/grpc/codes"
47 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053048)
49
50const (
51 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070053 //HsiaFlow flow category
54 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056 //EapolFlow flow category
57 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053058
Manikkaraj kb1d51442019-07-23 10:41:02 -040059 //DhcpFlow flow category
60 DhcpFlow = "DHCP_FLOW"
61
Esin Karamanccb714b2019-11-29 15:02:06 +000062 //MulticastFlow flow category
63 MulticastFlow = "MULTICAST_FLOW"
64
Esin Karamanae41e2b2019-12-17 18:13:13 +000065 //IgmpFlow flow category
66 IgmpFlow = "IGMP_FLOW"
67
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //IPProtoDhcp flow category
69 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //IPProtoIgmp flow category
72 IPProtoIgmp = 2
73
74 //EapEthType eapethtype value
75 EapEthType = 0x888e
76 //LldpEthType lldp ethtype value
77 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000078 //IPv4EthType IPv4 ethernet type value
79 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080
81 //IgmpProto proto value
82 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053083
Andrea Campanella7acc0b92020-02-14 09:20:49 +010084 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
85 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040086
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //DefaultMgmtVlan default vlan value
88 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053089
manikkaraj kbf256be2019-03-25 00:13:48 +053090 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091
David K. Bainbridge82efc492019-09-04 09:57:11 -070092 //Upstream constant
93 Upstream = "upstream"
94 //Downstream constant
95 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000096 //Multicast constant
97 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070098 //PacketTagType constant
99 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700100 //Untagged constant
101 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700102 //SingleTag constant
103 SingleTag = "single_tag"
104 //DoubleTag constant
105 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530106
107 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108
109 //EthType constant
110 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //EthDst constant
112 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 //TPID constant
114 TPID = "tpid"
115 //IPProto constant
116 IPProto = "ip_proto"
117 //InPort constant
118 InPort = "in_port"
119 //VlanVid constant
120 VlanVid = "vlan_vid"
121 //VlanPcp constant
122 VlanPcp = "vlan_pcp"
123
124 //UDPDst constant
125 UDPDst = "udp_dst"
126 //UDPSrc constant
127 UDPSrc = "udp_src"
128 //Ipv4Dst constant
129 Ipv4Dst = "ipv4_dst"
130 //Ipv4Src constant
131 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700132 //Metadata constant
133 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700134 //TunnelID constant
135 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700136 //Output constant
137 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138 //GroupID constant
139 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700140 // Actions
141
142 //PopVlan constant
143 PopVlan = "pop_vlan"
144 //PushVlan constant
145 PushVlan = "push_vlan"
146 //TrapToHost constant
147 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400148 //MaxMeterBand constant
149 MaxMeterBand = 2
150 //VlanPCPMask contant
151 VlanPCPMask = 0xFF
152 //VlanvIDMask constant
153 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000154 //IntfID constant
155 IntfID = "intfId"
156 //OnuID constant
157 OnuID = "onuId"
158 //UniID constant
159 UniID = "uniId"
160 //PortNo constant
161 PortNo = "portNo"
162 //AllocID constant
163 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000164
165 //NoneOnuID constant
166 NoneOnuID = -1
167 //NoneUniID constant
168 NoneUniID = -1
169 //NoneGemPortID constant
170 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530171
172 // BinaryStringPrefix is binary string prefix
173 BinaryStringPrefix = "0b"
174 // BinaryBit1 is binary bit 1 expressed as a character
175 BinaryBit1 = '1'
manikkaraj kbf256be2019-03-25 00:13:48 +0530176)
177
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400178type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700179 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400180 gemPort uint32
181}
182
Girish Gowdra3d633032019-12-10 16:37:05 +0530183type pendingFlowDeleteKey struct {
184 intfID uint32
185 onuID uint32
186 uniID uint32
187}
188
189type tpLockKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193}
194
Gamze Abakafee36392019-10-03 11:17:24 +0000195type schedQueue struct {
196 direction tp_pb.Direction
197 intfID uint32
198 onuID uint32
199 uniID uint32
200 tpID uint32
201 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700202 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000203 meterID uint32
204 flowMetadata *voltha.FlowMetadata
205}
206
Esin Karamanccb714b2019-11-29 15:02:06 +0000207type queueInfoBrief struct {
208 gemPortID uint32
209 servicePriority uint32
210}
211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700212//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530213type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000214 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000215 deviceHandler *DeviceHandler
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000217 onuIdsLock sync.RWMutex
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
219 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700220 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
221 onuGemInfo [][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
222 onuGemInfoLock []sync.RWMutex // lock by Pon Port
223 pendingFlowDelete sync.Map
Girish Gowdra3d633032019-12-10 16:37:05 +0530224 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Esin Karamanccb714b2019-11-29 15:02:06 +0000225 perUserFlowHandleLock *mapmutex.Mutex
226 interfaceToMcastQueueMap map[uint32]*queueInfoBrief /*pon interface -> multicast queue map. Required to assign GEM to a bucket during group population*/
manikkaraj kbf256be2019-03-25 00:13:48 +0530227}
228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
npujarec5762e2020-01-01 14:08:48 +0530230func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000231 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 var err error
234 var idx uint32
235
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 flowMgr.deviceHandler = dh
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000238 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000239 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
240 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530241 return nil
242 }
William Kurkian740a09c2019-10-23 17:07:38 -0400243 flowMgr.onuIdsLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
245 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700247 flowMgr.onuGemInfo = make([][]rsrcMgr.OnuGemInfo, ponPorts)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530248 //Load the onugem info cache from kv store on flowmanager start
249 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530250 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000251 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530252 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530253 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530254 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700256 flowMgr.onuGemInfoLock = make([]sync.RWMutex, ponPorts)
Girish Gowdra3d633032019-12-10 16:37:05 +0530257 flowMgr.pendingFlowDelete = sync.Map{}
Girish Gowdrab77ded92020-04-08 11:45:05 -0700258 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(300, 100000000, 10000000, 1.1, 0.2)
Esin Karamanccb714b2019-11-29 15:02:06 +0000259 flowMgr.interfaceToMcastQueueMap = make(map[uint32]*queueInfoBrief)
260 //load interface to multicast queue map from kv store
npujarec5762e2020-01-01 14:08:48 +0530261 flowMgr.loadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000262 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530263 return &flowMgr
264}
265
Neha Sharma96b7bf22020-06-15 10:37:32 +0000266func (f *OpenOltFlowMgr) generateStoredFlowID(ctx context.Context, flowID uint32, direction string) (uint64, error) {
David K. Bainbridge82efc492019-09-04 09:57:11 -0700267 if direction == Upstream {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000268 logger.Debugw(ctx, "upstream-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700269 return 0x1<<15 | uint64(flowID), nil
David K. Bainbridge82efc492019-09-04 09:57:11 -0700270 } else if direction == Downstream {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000271 logger.Debugw(ctx, "downstream-flow-not-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700272 return uint64(flowID), nil
Esin Karamanccb714b2019-11-29 15:02:06 +0000273 } else if direction == Multicast {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Debugw(ctx, "multicast-flow-shifting-id", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000275 return 0x2<<15 | uint64(flowID), nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400276 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530277 return 0, olterrors.NewErrInvalidValue(log.Fields{"direction": direction}, nil).Log()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400278 }
279}
280
npujarec5762e2020-01-01 14:08:48 +0530281func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000282 logger.Debugw(ctx, "registering-flow-for-device ",
Shrey Baid26912972020-04-16 21:02:31 +0530283 log.Fields{
284 "flow": flowFromCore,
285 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000286 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
287 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
288 if !ok {
289 flowIDList = []uint32{deviceFlow.FlowId}
290 }
291 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
292 f.flowsUsedByGemPort[gemPK] = flowIDList
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530293 // update the flowids for a gem to the KVstore
npujarec5762e2020-01-01 14:08:48 +0530294 f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400295}
296
npujarec5762e2020-01-01 14:08:48 +0530297func (f *OpenOltFlowMgr) divideAndAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000298 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
299 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) {
Gamze Abakafee36392019-10-03 11:17:24 +0000300 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530301 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700302 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530303
Neha Sharma96b7bf22020-06-15 10:37:32 +0000304 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530305 "device-id": f.deviceHandler.device.Id,
306 "intf-id": intfID,
307 "onu-id": onuID,
308 "uni-id": uniID,
309 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700310 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530311 "action": actionInfo,
312 "usmeter-iD": UsMeterID,
313 "dsmeter-iD": DsMeterID,
314 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400315 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
316 // is because the flow is an NNI flow and there would be no onu resources associated with it
317 // TODO: properly deal with NNI flows
Manikkaraj kb1d51442019-07-23 10:41:02 -0400318 if onuID <= 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000319 logger.Errorw(ctx, "no-onu-id-for-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530320 log.Fields{
321 "port-no": portNo,
322 "classifer": classifierInfo,
323 "action": actionInfo,
324 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530325 return
326 }
327
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700328 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000329 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530330 "uni": uni,
331 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530332
333 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
334 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000335 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530336 "device-id": f.deviceHandler.device.Id,
337 "intf-id": intfID,
338 "onu-id": onuID,
339 "uni-id": uniID,
340 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700341 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530342 "action": actionInfo,
343 "usmeter-id": UsMeterID,
344 "dsmeter-id": DsMeterID,
345 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530346 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530347 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000348 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530349 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
350 return
351 }
352 args := make(map[string]uint32)
353 args[IntfID] = intfID
354 args[OnuID] = onuID
355 args[UniID] = uniID
356 args[PortNo] = portNo
357 args[AllocID] = allocID
358
359 /* Flows can be added specific to gemport if p-bits are received.
360 * If no pbit mentioned then adding flows for all gemports
361 */
npujarec5762e2020-01-01 14:08:48 +0530362 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530363 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
364 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000365 logger.Errorw(ctx, "failed-to-acquire-per-user-flow-handle-lock",
Shrey Baid26912972020-04-16 21:02:31 +0530366 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -0700367 "intf-id": intfID,
368 "onu-id": onuID,
369 "uni-id": uniID,
370 "flow-id": flow.Id,
371 "flow-cookie": flow.Cookie,
372 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400373 return
374 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530375}
376
salmansiddiqui7ac62132019-08-22 03:58:50 +0000377// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530378func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400379
Neha Sharma96b7bf22020-06-15 10:37:32 +0000380 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530381 log.Fields{"dir": sq.direction,
382 "intf-id": sq.intfID,
383 "onu-id": sq.onuID,
384 "uni-id": sq.uniID,
385 "tp-id": sq.tpID,
386 "meter-id": sq.meterID,
387 "tp-inst": sq.tpInst,
388 "flowmetadata": sq.flowMetadata,
389 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Gamze Abakafee36392019-10-03 11:17:24 +0000391 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000392 if err != nil {
393 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 }
395
396 /* Lets make a simple assumption that if the meter-id is present on the KV store,
397 * then the scheduler and queues configuration is applied on the OLT device
398 * in the given direction.
399 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530402 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530404 return olterrors.NewErrNotFound("meter",
405 log.Fields{"intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000410
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000412 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000413 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530416 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800417 "unsupported": "meter-id",
418 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530419 "meter-id-in-flow": sq.meterID,
420 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000422
Neha Sharma96b7bf22020-06-15 10:37:32 +0000423 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530424 log.Fields{
425 "meter-id": sq.meterID,
426 "direction": Direction,
427 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000428
Gamze Abakafee36392019-10-03 11:17:24 +0000429 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000430 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000431 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000432 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000434
435 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530436 return olterrors.NewErrNotFound("scheduler-config",
437 log.Fields{
438 "intf-id": sq.intfID,
439 "direction": sq.direction,
440 "tp-inst": sq.tpInst,
441 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000442 }
443
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000445 if sq.flowMetadata != nil {
446 for _, meter := range sq.flowMetadata.Meters {
447 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530450 log.Fields{"meterConfig": meterConfig,
451 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 break
453 }
454 }
455 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000456 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 }
458 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530459 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800460 "reason": "Could-not-get-meterbands-from-flowMetadata",
461 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530462 "meter-id": sq.meterID,
463 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000465 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530466 log.Fields{"Bands": meterConfig.Bands,
467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530469 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800470 "reason": "Invalid-number-of-bands-in-meter",
471 "meterband-count": len(meterConfig.Bands),
472 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
476 cir := meterConfig.Bands[0].Rate
477 cbs := meterConfig.Bands[0].BurstSize
478 eir := meterConfig.Bands[1].Rate
479 ebs := meterConfig.Bands[1].BurstSize
480 pir := cir + eir
481 pbs := cbs + ebs
482 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
483
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700484 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000485 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486
npujarec5762e2020-01-01 14:08:48 +0530487 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530488 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
489 log.Fields{"intf-id": sq.intfID,
490 "direction": sq.direction,
491 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 }
493
salmansiddiqui7ac62132019-08-22 03:58:50 +0000494 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 * store the meter id on the KV store, for further reference.
496 */
npujarec5762e2020-01-01 14:08:48 +0530497 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530498 return olterrors.NewErrAdapter("failed-updating-meter-id",
499 log.Fields{"onu-id": sq.onuID,
500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000503 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530504 log.Fields{"direction": Direction,
505 "Meter": meterConfig,
506 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 return nil
508}
509
npujarec5762e2020-01-01 14:08:48 +0530510func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000511 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000512
513 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530514 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
515 log.Fields{"intf-id": sq.intfID,
516 "direction": sq.direction,
517 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000518 }
519
Neha Sharma96b7bf22020-06-15 10:37:32 +0000520 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530521 log.Fields{
522 "direction": sq.direction,
523 "TrafficScheds": TrafficSched,
524 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530525 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000526 IntfId: sq.intfID, OnuId: sq.onuID,
527 UniId: sq.uniID, PortNo: sq.uniPort,
528 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000529 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000530 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530532 "direction": sq.direction,
533 "traffic-queues": trafficQueues,
534 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535
536 // On receiving the CreateTrafficQueues request, the driver should create corresponding
537 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530539 log.Fields{"direction": sq.direction,
540 "traffic-queues": trafficQueues,
541 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530542 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
544 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000545 TrafficQueues: trafficQueues,
546 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530547 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000548 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530550 "direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
Esin Karamanccb714b2019-11-29 15:02:06 +0000554 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000556 if len(multicastTrafficQueues) > 0 {
557 if _, present := f.interfaceToMcastQueueMap[sq.intfID]; !present {
558 //assumed that there is only one queue per PON for the multicast service
559 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
560 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000562 multicastQueuePerPonPort := multicastTrafficQueues[0]
563 f.interfaceToMcastQueueMap[sq.intfID] = &queueInfoBrief{
564 gemPortID: multicastQueuePerPonPort.GemportId,
565 servicePriority: multicastQueuePerPonPort.Priority,
566 }
567 //also store the queue info in kv store
npujarec5762e2020-01-01 14:08:48 +0530568 f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID,
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 multicastQueuePerPonPort.GemportId,
570 multicastQueuePerPonPort.Priority)
Shrey Baid26912972020-04-16 21:02:31 +0530571
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 }
574 }
575 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576 return nil
577}
578
salmansiddiqui7ac62132019-08-22 03:58:50 +0000579// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530580func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581
582 var Direction string
583 var SchedCfg *tp_pb.SchedulerConfig
584 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530586 log.Fields{
587 "direction": sq.direction,
588 "intf-id": sq.intfID,
589 "onu-id": sq.onuID,
590 "uni-id": sq.uniID,
591 "uni-port": sq.uniPort,
592 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000593 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000594 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400595 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000596 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400598 Direction = "downstream"
599 }
600
Girish Kumar8f73fe02019-12-09 13:19:37 +0000601 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530602 return olterrors.NewErrNotFound("scheduler-config",
603 log.Fields{
604 "int-id": sq.intfID,
605 "direction": sq.direction,
606 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000607 }
608
npujarec5762e2020-01-01 14:08:48 +0530609 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530611 return olterrors.NewErrNotFound("meter",
612 log.Fields{
613 "onu-id": sq.onuID,
614 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400615 }
616 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000617 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530618 log.Fields{
619 "direction": Direction,
620 "intf-id": sq.intfID,
621 "onu-id": sq.onuID,
622 "uni-id": sq.uniID,
623 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624 return nil
625 }
626 cir := KVStoreMeter.Bands[0].Rate
627 cbs := KVStoreMeter.Bands[0].BurstSize
628 eir := KVStoreMeter.Bands[1].Rate
629 ebs := KVStoreMeter.Bands[1].BurstSize
630 pir := cir + eir
631 pbs := cbs + ebs
632
633 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
634
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700635 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000636 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000637
Neha Sharma96b7bf22020-06-15 10:37:32 +0000638 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000639 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530640 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
641 log.Fields{
642 "intf-id": sq.intfID,
643 "direction": sq.direction,
644 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000645 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400646
npujarec5762e2020-01-01 14:08:48 +0530647 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000648 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
649 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000650 TrafficQueues: TrafficQueues,
651 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000652 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530653 log.Fields{
654 "intf-id": sq.intfID,
655 "traffic-queues": TrafficQueues,
656 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400657 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000658 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530659 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000660 IntfId: sq.intfID, OnuId: sq.onuID,
661 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000663 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530664 log.Fields{
665 "intf-id": sq.intfID,
666 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400667 }
668
Neha Sharma96b7bf22020-06-15 10:37:32 +0000669 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000670
671 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400672 * delete the meter id on the KV store.
673 */
npujarec5762e2020-01-01 14:08:48 +0530674 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530676 return olterrors.NewErrAdapter("unable-to-remove-meter",
677 log.Fields{
678 "onu": sq.onuID,
679 "meter": KVStoreMeter.MeterId,
680 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
684 "meter-id": KVStoreMeter.MeterId,
685 "dir": Direction,
686 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 return err
688}
689
Gamze Abakafee36392019-10-03 11:17:24 +0000690// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700691func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000692 var allocIDs []uint32
693 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530694 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530695 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000696 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000697
npujarec5762e2020-01-01 14:08:48 +0530698 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
699 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530702
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530704 "intf-id": intfID,
705 "onu-id": onuID,
706 "uni-id": uniID,
707 "device-id": f.deviceHandler.device.Id,
708 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530709
Manikkaraj kb1d51442019-07-23 10:41:02 -0400710 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530711 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000712 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000713 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530714 log.Fields{
715 "path": tpPath,
716 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530717 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000718 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530719 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000720 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530721 log.Fields{
722 "error": err,
723 "tp-id": TpID,
724 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000725 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530726 }
npujarec5762e2020-01-01 14:08:48 +0530727 f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530728 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000729 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530730 log.Fields{
731 "uni": uni,
732 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530733 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530734 }
Gamze Abakafee36392019-10-03 11:17:24 +0000735
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700736 switch tpInst := techProfileInstance.(type) {
737 case *tp.TechProfile:
738 if UsMeterID != 0 {
739 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
740 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
741 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700743 log.Fields{
744 "error": err,
745 "meter-id": UsMeterID,
746 "device-id": f.deviceHandler.device.Id})
747 return 0, nil, nil
748 }
749 }
750 if DsMeterID != 0 {
751 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
752 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
753 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700755 log.Fields{
756 "error": err,
757 "meter-id": DsMeterID,
758 "device-id": f.deviceHandler.device.Id})
759 return 0, nil, nil
760 }
761 }
762 allocID := tpInst.UsScheduler.AllocID
763 for _, gem := range tpInst.UpstreamGemPortAttributeList {
764 gemPortIDs = append(gemPortIDs, gem.GemportID)
765 }
766 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000767
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700768 if tpInstanceExists {
769 return allocID, gemPortIDs, techProfileInstance
770 }
771
772 for _, gemPortID := range gemPortIDs {
773 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
774 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000775 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700776 log.Fields{
777 "alloc-ids": allocIDs,
778 "gemports": allgemPortIDs,
779 "device-id": f.deviceHandler.device.Id})
780 // Send Tconts and GEM ports to KV store
781 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530782 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783 case *tp.EponProfile:
784 // CreateSchedulerQueues for EPON needs to be implemented here
785 // when voltha-protos for EPON is completed.
786 allocID := tpInst.AllocID
787 for _, gem := range tpInst.UpstreamQueueAttributeList {
788 gemPortIDs = append(gemPortIDs, gem.GemportID)
789 }
790 allocIDs = appendUnique(allocIDs, allocID)
791
792 if tpInstanceExists {
793 return allocID, gemPortIDs, techProfileInstance
794 }
795
796 for _, gemPortID := range gemPortIDs {
797 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
798 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700800 log.Fields{
801 "alloc-ids": allocIDs,
802 "gemports": allgemPortIDs,
803 "device-id": f.deviceHandler.device.Id})
804 // Send Tconts and GEM ports to KV store
805 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
806 return allocID, gemPortIDs, techProfileInstance
807 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700809 log.Fields{
810 "tpInst": tpInst})
811 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530812 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530813}
814
npujarec5762e2020-01-01 14:08:48 +0530815func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530816
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530818 log.Fields{
819 "intf-id": intfID,
820 "onu-id": onuID,
821 "uni-id": uniID,
822 "alloc-id": allocID,
823 "gemport-ids": gemPortIDs,
824 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530825 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530826 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000827 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530828 }
npujarec5762e2020-01-01 14:08:48 +0530829 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
npujarec5762e2020-01-01 14:08:48 +0530832 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000833 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000835 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400836 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530837 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400838 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530839}
840
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000842 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530843 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000844 for _, intfID := range techRange.IntfIds {
845 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400846 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530848 log.Fields{
849 "intf-id": intfID,
850 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530851 }
852 }
853 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400854 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530855 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530856 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800857 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530858 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
859 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530862 log.Fields{
863 "numofTech": tpCount,
864 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
865 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530866 return nil
867}
868
npujarec5762e2020-01-01 14:08:48 +0530869func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530870 portNo uint32, uplinkClassifier map[string]interface{},
871 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000872 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700873 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000874 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530875 log.Fields{
876 "uplinkClassifier": uplinkClassifier,
877 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000879 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530880 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530881}
882
npujarec5762e2020-01-01 14:08:48 +0530883func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530884 portNo uint32, downlinkClassifier map[string]interface{},
885 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000886 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700887 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530889 log.Fields{
890 "downlinkClassifier": downlinkClassifier,
891 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400892 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
893 if vlan, exists := downlinkClassifier[VlanVid]; exists {
894 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700895 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000896 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
897 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530898 log.Fields{
899 "flow": logicalFlow,
900 "device-id": f.deviceHandler.device.Id,
901 "onu-id": onuID,
902 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800903 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400904 }
905 }
906 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530907 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400908
Manikkaraj k884c1242019-04-11 16:26:42 +0530909 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700910 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400911 // vlan_vid is a uint32. must be type asserted as such or conversion fails
912 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530913 if ok {
914 downlinkAction[VlanVid] = dlClVid & 0xfff
915 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530916 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530917 "reason": "failed-to-convert-vlanid-classifier",
918 "vlan-id": VlanVid,
919 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530920 }
921
David K. Bainbridge794735f2020-02-11 21:01:37 -0800922 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000923 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530924}
925
npujarec5762e2020-01-01 14:08:48 +0530926func (f *OpenOltFlowMgr) addHSIAFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530927 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000928 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530929 /* One of the OLT platform (Broadcom BAL) requires that symmetric
930 flows require the same flow_id to be used across UL and DL.
931 Since HSIA flow is the only symmetric flow currently, we need to
932 re-use the flow_id across both direction. The 'flow_category'
933 takes priority over flow_cookie to find any available HSIA_FLOW
934 id for the ONU.
935 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530937 log.Fields{
938 "intf-id": intfID,
939 "onu-id": onuID,
940 "uni-id": uniID,
941 "device-id": f.deviceHandler.device.Id,
942 "classifier": classifier,
943 "action": action,
944 "direction": direction,
945 "alloc-id": allocID,
946 "gemport-id": gemPortID,
947 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530948 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000949 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400950 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000951 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
954 "vlan-pbit": vlanPbit,
955 "intf-id": intfID,
956 "onu-id": onuID,
957 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800958 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000959 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530960 log.Fields{
961 "vlan-pcp": VlanPcp,
962 "intf-id": intfID,
963 "onu-id": onuID,
964 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400965 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000966 if _, ok := classifier[VlanVid]; ok {
967 vlanVid = classifier[VlanVid].(uint32)
Shrey Baid26912972020-04-16 21:02:31 +0530968 log.Debugw("found-vlan-in-the-flow",
969 log.Fields{
970 "vlan-vid": vlanVid,
971 "intf-id": intfID,
972 "onu-id": onuID,
973 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000974 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +0530976 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530978 log.Fields{
979 "device-id": f.deviceHandler.device.Id,
980 "intf-id": intfID,
981 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800982 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530983 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000984 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +0530985 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530986 return olterrors.NewErrNotFound("hsia-flow-id",
987 log.Fields{
988 "direction": direction,
989 "device-id": f.deviceHandler.device.Id,
990 "intf-id": intfID,
991 "onu-id": onuID,
992 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530993 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800994 classifierProto, err := makeOpenOltClassifierField(classifier)
995 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530996 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530997 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
1000 "classifier": *classifierProto,
1001 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001002 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001003 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301004 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301005 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001006 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301007 log.Fields{
1008 "action": *actionProto,
1009 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001010 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301011 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301012 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 log.Fields{
1014 "classifier": classifier,
1015 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301016 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301018 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001019 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1020 OnuId: int32(onuID),
1021 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001022 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301023 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001024 AllocId: int32(allocID),
1025 NetworkIntfId: int32(networkIntfID),
1026 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301027 Classifier: classifierProto,
1028 Action: actionProto,
1029 Priority: int32(logicalFlow.Priority),
1030 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001031 PortNo: portNo,
1032 TechProfileId: tpID,
1033 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001034 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301035 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301036 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301038 log.Fields{"direction": direction,
1039 "device-id": f.deviceHandler.device.Id,
1040 "flow": flow,
1041 "intf-id": intfID,
1042 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1044 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1045 flow.OnuId,
1046 flow.UniId,
1047 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301048 return olterrors.NewErrPersistence("update", "flow", flowID,
1049 log.Fields{
1050 "flow": flow,
1051 "device-id": f.deviceHandler.device.Id,
1052 "intf-id": intfID,
1053 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 }
1055 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301056}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001057
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001058func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1059 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1060 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301061
Neha Sharma96b7bf22020-06-15 10:37:32 +00001062 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301063 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301064 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301066 "action": action,
1067 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301069 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301070
1071 // Clear the action map
1072 for k := range action {
1073 delete(action, k)
1074 }
1075
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001076 action[TrapToHost] = true
1077 classifier[UDPSrc] = uint32(68)
1078 classifier[UDPDst] = uint32(67)
1079 classifier[PacketTagType] = SingleTag
1080 delete(classifier, VlanVid)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301081
Neha Sharma96b7bf22020-06-15 10:37:32 +00001082 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301083 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "device-id": f.deviceHandler.device.Id,
1087 "intf-id": intfID,
1088 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301090 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301091
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, DhcpFlow, 0 /*classifier[VLAN_PCP].(uint32)*/)
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301093
1094 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301095 return olterrors.NewErrNotFound("flow",
1096 log.Fields{
1097 "interface-id": intfID,
1098 "gem-port": gemPortID,
1099 "cookie": flowStoreCookie,
1100 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301102 }
1103
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301105 log.Fields{
1106 "ul_classifier": classifier,
1107 "ul_action": action,
1108 "uplinkFlowId": flowID,
1109 "intf-id": intfID,
1110 "onu-id": onuID,
1111 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301112
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 classifierProto, err := makeOpenOltClassifierField(classifier)
1114 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301115 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301116 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001118 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301120 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301121 }
1122
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001124 OnuId: int32(onuID),
1125 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301126 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001127 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 AllocId: int32(allocID),
1129 NetworkIntfId: int32(networkIntfID),
1130 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301131 Classifier: classifierProto,
1132 Action: actionProto,
1133 Priority: int32(logicalFlow.Priority),
1134 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001135 PortNo: portNo,
1136 TechProfileId: tpID,
1137 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301139 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001140 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001141 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301142 log.Fields{
1143 "device-id": f.deviceHandler.device.Id,
1144 "flow-id": flowID,
1145 "intf-id": intfID,
1146 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1148 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1149 dhcpFlow.OnuId,
1150 dhcpFlow.UniId,
1151 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301152 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1153 log.Fields{
1154 "flow": dhcpFlow,
1155 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156 }
1157
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301159}
1160
Esin Karamanae41e2b2019-12-17 18:13:13 +00001161//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301162func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001163 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1164 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001165}
1166
1167//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301168func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001169 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001172 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301173 return olterrors.NewErrNotFound("nni-interface-id",
1174 log.Fields{
1175 "classifier": classifier,
1176 "action": action,
1177 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001178 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001179 }
1180
1181 // Clear the action map
1182 for k := range action {
1183 delete(action, k)
1184 }
1185
1186 action[TrapToHost] = true
1187 classifier[PacketTagType] = SingleTag
1188 delete(classifier, VlanVid)
1189
Neha Sharma96b7bf22020-06-15 10:37:32 +00001190 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301191 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001192 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001194 }
1195
npujarec5762e2020-01-01 14:08:48 +05301196 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, flowType, 0, 0 /*classifier[VLAN_PCP].(uint32)*/)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197
1198 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301199 return olterrors.NewErrNotFound("flow-id",
1200 log.Fields{
1201 "intf-id": intfID,
1202 "oni-id": onuID,
1203 "cookie": flowStoreCookie,
1204 "flow-type": flowType,
1205 "device-id": f.deviceHandler.device.Id,
1206 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001207 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208 }
1209
Neha Sharma96b7bf22020-06-15 10:37:32 +00001210 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301211 log.Fields{
1212 "ul_classifier": classifier,
1213 "ul_action": action,
1214 "uplinkFlowId": flowID,
1215 "flowType": flowType,
1216 "device-id": f.deviceHandler.device.Id,
1217 "intf-id": intfID,
1218 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 classifierProto, err := makeOpenOltClassifierField(classifier)
1221 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301222 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001223 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001224 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301225 log.Fields{
1226 "classifier": *classifierProto,
1227 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001228 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001229 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301230 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001231 }
1232
David K. Bainbridge794735f2020-02-11 21:01:37 -08001233 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001234 OnuId: int32(onuID),
1235 UniId: int32(uniID),
1236 FlowId: flowID,
1237 FlowType: Upstream,
1238 AllocId: int32(allocID),
1239 NetworkIntfId: int32(networkIntfID),
1240 GemportId: int32(gemPortID),
1241 Classifier: classifierProto,
1242 Action: actionProto,
1243 Priority: int32(logicalFlow.Priority),
1244 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001245 PortNo: portNo,
1246 TechProfileId: tpID,
1247 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001248
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301250 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001252 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1255 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1256 flow.OnuId,
1257 flow.UniId,
1258 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301259 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260 }
1261
David K. Bainbridge794735f2020-02-11 21:01:37 -08001262 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263}
1264
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001265// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001266func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1267 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1268 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301270 log.Fields{
1271 "intf-id": intfID,
1272 "onu-id": onuID,
1273 "port-no": portNo,
1274 "alloc-id": allocID,
1275 "gemport-id": gemPortID,
1276 "vlan-id": vlanID,
1277 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301278
1279 uplinkClassifier := make(map[string]interface{})
1280 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301281
manikkaraj kbf256be2019-03-25 00:13:48 +05301282 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001283 uplinkClassifier[EthType] = uint32(EapEthType)
1284 uplinkClassifier[PacketTagType] = SingleTag
1285 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001286 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301287 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001288 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001289 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301290 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001291 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301292 "device-id": f.deviceHandler.device.Id,
1293 "onu-id": onuID,
1294 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001295 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301296 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301297 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001298 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301299 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301300 return olterrors.NewErrNotFound("flow-id",
1301 log.Fields{
1302 "intf-id": intfID,
1303 "onu-id": onuID,
1304 "coookie": flowStoreCookie,
1305 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301307 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301309 log.Fields{
1310 "ul_classifier": uplinkClassifier,
1311 "ul_action": uplinkAction,
1312 "uplinkFlowId": uplinkFlowID,
1313 "device-id": f.deviceHandler.device.Id,
1314 "intf-id": intfID,
1315 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301316
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1318 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301319 return olterrors.NewErrInvalidValue(log.Fields{
1320 "classifier": uplinkClassifier,
1321 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301322 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001323 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301324 log.Fields{
1325 "classifier": *classifierProto,
1326 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001327 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001328 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301329 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301330 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001331 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301332 log.Fields{
1333 "action": *actionProto,
1334 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001335 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301336 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301337 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301339 "action": action,
1340 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301342 }
1343
David K. Bainbridge794735f2020-02-11 21:01:37 -08001344 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 OnuId: int32(onuID),
1346 UniId: int32(uniID),
1347 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001348 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001349 AllocId: int32(allocID),
1350 NetworkIntfId: int32(networkIntfID),
1351 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301352 Classifier: classifierProto,
1353 Action: actionProto,
1354 Priority: int32(logicalFlow.Priority),
1355 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001356 PortNo: portNo,
1357 TechProfileId: tpID,
1358 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301360 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001362 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301363 log.Fields{
1364 "device-id": f.deviceHandler.device.Id,
1365 "onu-id": onuID,
1366 "intf-id": intfID,
1367 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 flowCategory := "EAPOL"
1369 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1370 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1371 upstreamFlow.OnuId,
1372 upstreamFlow.UniId,
1373 upstreamFlow.FlowId,
1374 /* lowCategory, */
1375 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301376 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1377 log.Fields{
1378 "flow": upstreamFlow,
1379 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301380 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301382}
1383
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001385 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001386
1387 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1388 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1389 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001390 if vlanID != ReservedVlan {
1391 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001392 classifier.OVid = vid
1393 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301394 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001395 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1396 vid := uint32(metadata)
1397 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001398 classifier.IVid = vid
1399 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301400 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301401 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001402 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301403 classifier.OPbits = vlanPcp
1404 } else {
1405 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301406 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001407 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1408 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1409 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1410 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001411 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001412 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1413 classifier.PktTagType = pktTagType
1414
1415 switch pktTagType {
1416 case SingleTag:
1417 case DoubleTag:
1418 case Untagged:
1419 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001420 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301421 }
1422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301424}
1425
Gamze Abaka724d0852020-03-18 12:10:24 +00001426func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 var actionCmd openoltpb2.ActionCmd
1428 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301429 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001432 if _, ok := actionInfo[VlanPcp]; ok {
1433 action.Cmd.RemarkInnerPbits = true
1434 action.IPbits = actionInfo[VlanPcp].(uint32)
1435 if _, ok := actionInfo[VlanVid]; ok {
1436 action.Cmd.TranslateInnerTag = true
1437 action.IVid = actionInfo[VlanVid].(uint32)
1438 }
1439 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001440 } else if _, ok := actionInfo[PushVlan]; ok {
1441 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001443 if _, ok := actionInfo[VlanPcp]; ok {
1444 action.OPbits = actionInfo[VlanPcp].(uint32)
1445 action.Cmd.RemarkOuterPbits = true
1446 if _, ok := classifierInfo[VlanVid]; ok {
1447 action.IVid = classifierInfo[VlanVid].(uint32)
1448 action.Cmd.TranslateInnerTag = true
1449 }
1450 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001451 } else if _, ok := actionInfo[TrapToHost]; ok {
1452 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301453 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001454 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001456 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301457}
1458
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001459// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1461 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301462}
1463
Gamze Abakafee36392019-10-03 11:17:24 +00001464// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301465func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1466 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001467 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1468
Gamze Abakafee36392019-10-03 11:17:24 +00001469 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301470 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301471 olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301472 // return err
1473 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001474 }
Shrey Baid26912972020-04-16 21:02:31 +05301475 log.Debugw("tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001476 }
1477 return nil
1478}
1479
1480// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301481func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001482 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001483 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001484 }
npujarec5762e2020-01-01 14:08:48 +05301485 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301486 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1487 log.Fields{
1488 "tp-id": tpID,
1489 "uni-port-name": uniPortName,
1490 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001491 }
1492 return nil
1493}
1494
Neha Sharma96b7bf22020-06-15 10:37:32 +00001495func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301496 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001497 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 return 0
1499 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001500 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301501 log.Fields{
1502 "classifier": classifier,
1503 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301504 var jsonData []byte
1505 var flowString string
1506 var err error
1507 // TODO: Do we need to marshall ??
1508 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001509 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301510 return 0
1511 }
1512 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001513 if gemPortID != 0 {
1514 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301515 }
1516 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301518 hash := big.NewInt(0)
1519 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301520 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001521 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301522 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301523}
1524
npujarec5762e2020-01-01 14:08:48 +05301525func (f *OpenOltFlowMgr) getUpdatedFlowInfo(ctx context.Context, flow *openoltpb2.Flow, flowStoreCookie uint64, flowCategory string, deviceFlowID uint32, logicalFlowID uint64) *[]rsrcMgr.FlowInfo {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301526 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001527 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001528 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1529 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1530 */
1531 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001532 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001533 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001534 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001535 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001536 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301537 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001538 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301540 log.Fields{
1541 "flow-id": flow.FlowId,
1542 "device-id": f.deviceHandler.device.Id,
1543 "intf-id": intfID,
1544 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001545 //for _, f := range *existingFlows {
1546 // flows = append(flows, f)
1547 //}
1548 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001549 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001550 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301551 log.Fields{
1552 "updatedflow": flows,
1553 "flow-id": flow.FlowId,
1554 "onu-id": flow.OnuId,
1555 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301556 return &flows
1557}
1558
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001559//func (f *OpenOltFlowMgr) getUpdatedFlowInfo(flow *openolt_pb2.Flow, flowStoreCookie uint64, flowCategory string) *[]rsrcMgr.FlowInfo {
1560// var flows []rsrcMgr.FlowInfo = []rsrcMgr.FlowInfo{rsrcMgr.FlowInfo{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie}}
1561// var intfId uint32
1562// /* For flows which trap out of the NNI, the AccessIntfId is invalid
1563// (set to -1). In such cases, we need to refer to the NetworkIntfId .
1564// */
1565// if flow.AccessIntfId != -1 {
1566// intfId = uint32(flow.AccessIntfId)
1567// } else {
1568// intfId = uint32(flow.NetworkIntfId)
1569// }
1570// // Get existing flows matching flowid for given subscriber from KV store
1571// existingFlows := f.resourceMgr.GetFlowIDInfo(intfId, uint32(flow.OnuId), uint32(flow.UniId), flow.FlowId)
1572// if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001573// logger.Debugw(ctx, "Flow exists for given flowID, appending it to current flow", log.Fields{"flowID": flow.FlowId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001574// for _, f := range *existingFlows {
1575// flows = append(flows, f)
1576// }
1577// }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578// logger.Debugw(ctx, "Updated flows for given flowID and onuid", log.Fields{"updatedflow": flows, "flowid": flow.FlowId, "onu": flow.OnuId})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001579// return &flows
1580//}
1581
npujarec5762e2020-01-01 14:08:48 +05301582func (f *OpenOltFlowMgr) updateFlowInfoToKVStore(ctx context.Context, intfID int32, onuID int32, uniID int32, flowID uint32, flows *[]rsrcMgr.FlowInfo) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301584 "flow-id": flowID,
1585 "device-id": f.deviceHandler.device.Id,
1586 "intf-id": intfID,
1587 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301588 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001589 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301590 "device-id": f.deviceHandler.device.Id,
1591 "onu-id": onuID,
1592 "intf-id": intfID,
1593 "flow-id": flowID})
manikkaraj k17652a72019-05-06 09:06:36 -04001594 return err
1595 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301597 "device-id": f.deviceHandler.device.Id,
1598 "onu-id": onuID,
1599 "intf-id": intfID,
1600 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301601 return nil
1602}
1603
David K. Bainbridge794735f2020-02-11 21:01:37 -08001604func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001605
1606 var intfID uint32
1607 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1608 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1609 */
1610 if deviceFlow.AccessIntfId != -1 {
1611 intfID = uint32(deviceFlow.AccessIntfId)
1612 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001613 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001614 intfID = uint32(deviceFlow.NetworkIntfId)
1615 }
1616
Neha Sharma96b7bf22020-06-15 10:37:32 +00001617 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301618 "flow": *deviceFlow,
1619 "device-id": f.deviceHandler.device.Id,
1620 "intf-id": intfID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301621 _, err := f.deviceHandler.Client.FlowAdd(context.Background(), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001622
1623 st, _ := status.FromError(err)
1624 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001625 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001626 "err": err,
1627 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301628 "device-id": f.deviceHandler.device.Id,
1629 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301631 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001632
1633 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301635 log.Fields{"err": err,
1636 "device-flow": deviceFlow,
1637 "device-id": f.deviceHandler.device.Id,
1638 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301639 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001640 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001641 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301642 if deviceFlow.GemportId != -1 {
1643 // No need to register the flow if it is a trap on nni flow.
npujarec5762e2020-01-01 14:08:48 +05301644 f.registerFlow(ctx, logicalFlow, deviceFlow)
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301645 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301647 log.Fields{
1648 "flow": *deviceFlow,
1649 "device-id": f.deviceHandler.device.Id,
1650 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001652}
1653
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1655 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301656 log.Fields{
1657 "flow": *deviceFlow,
1658 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001659 _, err := f.deviceHandler.Client.FlowRemove(context.Background(), deviceFlow)
1660 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001661 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "err": err,
1665 "deviceFlow": deviceFlow,
1666 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001667 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001669 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001670 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001671
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001674 "of-flow-id": ofFlowID,
1675 "flow": *deviceFlow,
1676 "device-id": f.deviceHandler.device.Id,
1677 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301679}
1680
1681/*func register_flow(deviceFlow *openolt_pb2.Flow, logicalFlow *ofp.OfpFlowStats){
1682 //update core flows_proxy : flows_proxy.update('/', flows)
1683}
1684
1685func generateStoredId(flowId uint32, direction string)uint32{
1686
David K. Bainbridge82efc492019-09-04 09:57:11 -07001687 if direction == Upstream{
Neha Sharma96b7bf22020-06-15 10:37:32 +00001688 logger.Debug(ctx, "Upstream flow shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301689 return ((0x1 << 15) | flowId)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001690 }else if direction == Downstream{
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Debug(ctx, "Downstream flow not shifting flowid")
manikkaraj kbf256be2019-03-25 00:13:48 +05301692 return flowId
1693 }else{
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Errorw(ctx, "Unrecognized direction",log.Fields{"direction": direction})
manikkaraj kbf256be2019-03-25 00:13:48 +05301695 return flowId
1696 }
1697}
1698
1699*/
1700
David K. Bainbridge794735f2020-02-11 21:01:37 -08001701func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001702
1703 classifierInfo := make(map[string]interface{})
1704 actionInfo := make(map[string]interface{})
1705
1706 classifierInfo[EthType] = uint32(LldpEthType)
1707 classifierInfo[PacketTagType] = Untagged
1708 actionInfo[TrapToHost] = true
1709
1710 // LLDP flow is installed to trap LLDP packets on the NNI port.
1711 // We manage flow_id resource pool on per PON port basis.
1712 // Since this situation is tricky, as a hack, we pass the NNI port
1713 // index (network_intf_id) as PON port Index for the flow_id resource
1714 // pool. Also, there is no ONU Id available for trapping LLDP packets
1715 // on NNI port, use onu_id as -1 (invalid)
1716 // ****************** CAVEAT *******************
1717 // This logic works if the NNI Port Id falls within the same valid
1718 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1719 // we need to have a re-look at this.
1720 // *********************************************
1721
1722 var onuID = -1
1723 var uniID = -1
1724 var gemPortID = -1
1725
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301728 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001729 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301731 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001733 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001734 }
npujarec5762e2020-01-01 14:08:48 +05301735 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001736
1737 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301738 return olterrors.NewErrNotFound("flow-id",
1739 log.Fields{
1740 "interface-id": networkInterfaceID,
1741 "onu-id": onuID,
1742 "uni-id": uniID,
1743 "gem-port-id": gemPortID,
1744 "cookie": flowStoreCookie,
1745 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001746 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001747 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001748 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1749 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301750 return olterrors.NewErrInvalidValue(
1751 log.Fields{
1752 "classifier": classifierInfo,
1753 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001754 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301756 log.Fields{
1757 "classifier": *classifierProto,
1758 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001759 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001760 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301761 return olterrors.NewErrInvalidValue(
1762 log.Fields{
1763 "action": actionInfo,
1764 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001765 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301767 log.Fields{
1768 "action": *actionProto,
1769 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001770
1771 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1772 OnuId: int32(onuID), // OnuId not required
1773 UniId: int32(uniID), // UniId not used
1774 FlowId: flowID,
1775 FlowType: Downstream,
1776 NetworkIntfId: int32(networkInterfaceID),
1777 GemportId: int32(gemPortID),
1778 Classifier: classifierProto,
1779 Action: actionProto,
1780 Priority: int32(flow.Priority),
1781 Cookie: flow.Cookie,
1782 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001783 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301784 return olterrors.NewErrFlowOp("add", flowID,
1785 log.Fields{
1786 "flow": downstreamflow,
1787 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001788 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001789 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301790 log.Fields{
1791 "device-id": f.deviceHandler.device.Id,
1792 "onu-id": onuID,
1793 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001794 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1795 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1796 int32(onuID),
1797 int32(uniID),
1798 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301799 return olterrors.NewErrPersistence("update", "flow", flowID,
1800 log.Fields{
1801 "flow": downstreamflow,
1802 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001803 }
1804 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301805}
1806
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001807func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1808 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001809}
1810
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001811//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001813 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1814 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1815 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301817 log.Fields{
1818 "intf-id": intfID,
1819 "onu-id": onuID,
1820 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001822 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301823 return nil, olterrors.NewErrNotFound("onu-child-device",
1824 log.Fields{
1825 "onu-id": onuID,
1826 "intf-id": intfID,
1827 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 }
1829 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1830 //better to ad the device to cache here.
1831 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1832 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001833 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301834 log.Fields{
1835 "intf-id": intfID,
1836 "onu-id": onuID,
1837 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001838 }
1839
1840 return onuDev.(*OnuDevice), nil
1841}
1842
1843//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1845 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301846 log.Fields{
1847 "pon-port": intfID,
1848 "onu-id": onuID,
1849 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001850 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001852 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301853 return nil, olterrors.NewErrNotFound("onu",
1854 log.Fields{
1855 "interface-id": parentPortNo,
1856 "onu-id": onuID,
1857 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001858 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301859 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301861 log.Fields{
1862 "device-id": f.deviceHandler.device.Id,
1863 "child_device_id": onuDevice.Id,
1864 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301865 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301866}
1867
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868func findNextFlow(ctx context.Context, flow *ofp.OfpFlowStats) *ofp.OfpFlowStats {
1869 logger.Info(ctx, "unimplemented-flow %v", flow)
manikkaraj kbf256be2019-03-25 00:13:48 +05301870 return nil
1871}
1872
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873func (f *OpenOltFlowMgr) clearFlowsAndSchedulerForLogicalPort(ctx context.Context, childDevice *voltha.Device, logicalPort *voltha.LogicalPort) {
1874 logger.Info(ctx, "unimplemented-device %v, logicalport %v", childDevice, logicalPort)
manikkaraj kbf256be2019-03-25 00:13:48 +05301875}
1876
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001877func (f *OpenOltFlowMgr) decodeStoredID(id uint64) (uint64, string) {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001878 if id>>15 == 0x1 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07001879 return id & 0x7fff, Upstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001880 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001881 return id, Downstream
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001882}
1883
Neha Sharma96b7bf22020-06-15 10:37:32 +00001884func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1885 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301886 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301888 log.Fields{
1889 "intf-id": intfID,
1890 "onu-id": onuID,
1891 "uni-id": uniID,
1892 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001893 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301894 }
1895
1896 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001897 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301898 log.Fields{
1899 "msg": *delGemPortMsg,
1900 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1902 delGemPortMsg,
1903 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301904 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001905 onuDev.deviceType,
1906 onuDev.deviceID,
1907 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301908 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1909 log.Fields{
1910 "from-adapter": f.deviceHandler.device.Type,
1911 "to-adapter": onuDev.deviceType,
1912 "onu-id": onuDev.deviceID,
1913 "proxyDeviceID": onuDev.proxyDeviceID,
1914 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301915 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001916 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301917 log.Fields{
1918 "msg": delGemPortMsg,
1919 "from-adapter": f.deviceHandler.device.Type,
1920 "to-adapter": onuDev.deviceType,
1921 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301922 return nil
1923}
1924
Neha Sharma96b7bf22020-06-15 10:37:32 +00001925func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1926 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301927 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001928 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301929 log.Fields{
1930 "intf-id": intfID,
1931 "onu-id": onuID,
1932 "uni-id": uniID,
1933 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001934 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301935 }
1936
1937 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001938 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301939 log.Fields{
1940 "msg": *delTcontMsg,
1941 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301942 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
1943 delTcontMsg,
1944 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301945 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001946 onuDev.deviceType,
1947 onuDev.deviceID,
1948 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301949 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1950 log.Fields{
1951 "from-adapter": f.deviceHandler.device.Type,
1952 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1953 "proxyDeviceID": onuDev.proxyDeviceID,
1954 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301955 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001956 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301957 log.Fields{
1958 "msg": delTcontMsg,
1959 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301960 return nil
1961}
1962
Neha Sharma96b7bf22020-06-15 10:37:32 +00001963func (f *OpenOltFlowMgr) deletePendingFlows(ctx context.Context, Intf uint32, onuID int32, uniID int32) {
Girish Gowdra3d633032019-12-10 16:37:05 +05301964 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
1965 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); ok {
1966 if val.(int) > 0 {
1967 pnFlDels := val.(int) - 1
1968 if pnFlDels > 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001969 logger.Debugw(ctx, "flow-delete-succeeded--more-pending",
Shrey Baid26912972020-04-16 21:02:31 +05301970 log.Fields{
1971 "intf": Intf,
1972 "onu-id": onuID,
1973 "uni-id": uniID,
1974 "currpendingflowcnt": pnFlDels,
1975 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301976 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
1977 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001978 logger.Debugw(ctx, "all-pending-flow-deletes-handled--removing-entry-from-map",
Shrey Baid26912972020-04-16 21:02:31 +05301979 log.Fields{
1980 "intf": Intf,
1981 "onu-id": onuID,
1982 "uni-id": uniID,
1983 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301984 f.pendingFlowDelete.Delete(pnFlDelKey)
1985 }
1986 }
1987 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001988 logger.Debugw(ctx, "no-pending-delete-flows-found",
Shrey Baid26912972020-04-16 21:02:31 +05301989 log.Fields{
1990 "intf": Intf,
1991 "onu-id": onuID,
1992 "uni-id": uniID,
1993 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05301994
1995 }
1996
1997}
1998
Girish Gowdrac3037402020-01-22 20:29:53 +05301999// Once the gemport is released for a given onu, it also has to be cleared from local cache
2000// which was used for deriving the gemport->logicalPortNo during packet-in.
2001// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
2002// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002003func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002004
2005 f.onuGemInfoLock[intfID].Lock()
2006 defer f.onuGemInfoLock[intfID].Unlock()
2007
Neha Sharma96b7bf22020-06-15 10:37:32 +00002008 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05302009 log.Fields{
2010 "gem": gemPortID,
2011 "intf-id": intfID,
2012 "onu-id": onuID,
2013 "device-id": f.deviceHandler.device.Id,
2014 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdrac3037402020-01-22 20:29:53 +05302015 onugem := f.onuGemInfo[intfID]
serkant.uluderya96af4932020-02-20 16:58:48 -08002016 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05302017 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08002018 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05302019 // If the gemport is found, delete it from local cache.
2020 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08002021 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
2022 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05302024 log.Fields{
2025 "intf-id": intfID,
2026 "onu-id": onuID,
2027 "deletedgemport-id": gemPortID,
2028 "gemports": onu.GemPorts,
2029 "device-id": f.deviceHandler.device.Id})
Girish Gowdrac3037402020-01-22 20:29:53 +05302030 break
2031 }
2032 }
2033 break
2034 }
2035 }
2036}
2037
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302038//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002039// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302040func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302041 gemPortID int32, flowID uint32, flowDirection string,
2042 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002043
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002045 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302046 return olterrors.NewErrNotFound("tp-id",
2047 log.Fields{
2048 "flow": flow,
2049 "intf": Intf,
2050 "onu-id": onuID,
2051 "uni-id": uniID,
2052 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002053 }
Gamze Abakafee36392019-10-03 11:17:24 +00002054
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002055 if len(updatedFlows) >= 0 {
2056 // There are still flows referencing the same flow_id.
2057 // So the flow should not be freed yet.
2058 // For ex: Case of HSIA where same flow is shared
2059 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002060 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302061 olterrors.NewErrPersistence("update", "flow", flowID,
2062 log.Fields{
2063 "flow": updatedFlows,
2064 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002065 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002066 if len(updatedFlows) == 0 {
Girish Gowdra3d633032019-12-10 16:37:05 +05302067 // Do this for subscriber flows only (not trap from NNI flows)
2068 if onuID != -1 && uniID != -1 {
2069 pnFlDelKey := pendingFlowDeleteKey{Intf, uint32(onuID), uint32(uniID)}
2070 if val, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 logger.Debugw(ctx, "creating-entry-for-pending-flow-delete",
Shrey Baid26912972020-04-16 21:02:31 +05302072 log.Fields{
2073 "flow-id": flowID,
2074 "intf": Intf,
2075 "onu-id": onuID,
2076 "uni-id": uniID,
2077 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302078 f.pendingFlowDelete.Store(pnFlDelKey, 1)
2079 } else {
2080 pnFlDels := val.(int) + 1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Debugw(ctx, "updating-flow-delete-entry",
Shrey Baid26912972020-04-16 21:02:31 +05302082 log.Fields{
2083 "flow-id": flowID,
2084 "intf": Intf,
2085 "onu-id": onuID,
2086 "uni-id": uniID,
2087 "currPendingFlowCnt": pnFlDels,
2088 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +05302089 f.pendingFlowDelete.Store(pnFlDelKey, pnFlDels)
2090 }
2091
Neha Sharma96b7bf22020-06-15 10:37:32 +00002092 defer f.deletePendingFlows(ctx, Intf, onuID, uniID)
Girish Gowdra3d633032019-12-10 16:37:05 +05302093 }
2094
Neha Sharma96b7bf22020-06-15 10:37:32 +00002095 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302096 log.Fields{
2097 "Intf": Intf,
2098 "onu-id": onuID,
2099 "uni-id": uniID,
2100 "flow-id": flowID,
2101 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302102 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002103
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002104 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002105 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2106 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302107 log.Fields{
2108 "TP-PATH": tpPath,
2109 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302110 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002111 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302112 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2113 log.Fields{
2114 "tp-id": tpID,
2115 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002116 }
2117
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302118 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Gamze Abakafee36392019-10-03 11:17:24 +00002119 if f.isGemPortUsedByAnotherFlow(gemPK) {
2120 flowIDs := f.flowsUsedByGemPort[gemPK]
2121 for i, flowIDinMap := range flowIDs {
2122 if flowIDinMap == flowID {
2123 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302124 // everytime flowsUsedByGemPort cache is updated the same should be updated
2125 // in kv store by calling UpdateFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002126 f.flowsUsedByGemPort[gemPK] = flowIDs
npujarec5762e2020-01-01 14:08:48 +05302127 f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs)
Gamze Abakafee36392019-10-03 11:17:24 +00002128 break
2129 }
2130 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
Shrey Baid26912972020-04-16 21:02:31 +05302132 log.Fields{
2133 "gemport-id": gemPortID,
2134 "usedByFlows": flowIDs,
2135 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302136 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002137 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302139 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002140 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2141 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
npujarec5762e2020-01-01 14:08:48 +05302142 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002143 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002144 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302145 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2146 // by calling DeleteFlowIDsForGem
Gamze Abakafee36392019-10-03 11:17:24 +00002147 delete(f.flowsUsedByGemPort, gemPK)
npujarec5762e2020-01-01 14:08:48 +05302148 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2149 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002150 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302151 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2153 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302154 log.Fields{
2155 "err": err,
2156 "intf": Intf,
2157 "onu-id": onuID,
2158 "uni-id": uniID,
2159 "device-id": f.deviceHandler.device.Id,
2160 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302161 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002162 switch techprofileInst := techprofileInst.(type) {
2163 case *tp.TechProfile:
2164 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2165 if !ok {
2166 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
2167 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
2168 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2169 f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst})
2170 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2171 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2173 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002174 log.Fields{
2175 "intf": Intf,
2176 "onu-id": onuID,
2177 "uni-id": uniID,
2178 "device-id": f.deviceHandler.device.Id,
2179 "alloc-id": techprofileInst.UsScheduler.AllocID})
2180 }
2181 }
2182 case *tp.EponProfile:
npujarec5762e2020-01-01 14:08:48 +05302183 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID)
npujarec5762e2020-01-01 14:08:48 +05302184 f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002185 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302186 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002187 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2188 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302189 log.Fields{
2190 "intf": Intf,
2191 "onu-id": onuID,
2192 "uni-id": uniID,
2193 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002194 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302195 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002196 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002198 log.Fields{
2199 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002200 }
2201 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002202 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203 return nil
2204}
2205
David K. Bainbridge794735f2020-02-11 21:01:37 -08002206// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302207func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302208
Neha Sharma96b7bf22020-06-15 10:37:32 +00002209 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302210 log.Fields{
2211 "flowDirection": flowDirection,
2212 "flow": *flow,
2213 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002214
2215 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302216 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002217 return
2218 }
2219
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302220 var updatedFlows []rsrcMgr.FlowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302221 classifierInfo := make(map[string]interface{})
2222
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302224 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302226 return
2227 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302228
David K. Bainbridge794735f2020-02-11 21:01:37 -08002229 onuID := int32(onu)
2230 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302231
2232 for _, field := range flows.GetOfbFields(flow) {
2233 if field.Type == flows.IP_PROTO {
2234 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002235 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302236 }
2237 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002238 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302239 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002240 "flow-id": flow.Id,
2241 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302242 "onu-id": onuID,
2243 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302244
2245 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2246 onuID = -1
2247 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002248 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2249 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002250 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002251 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002252 log.Fields{
2253 "port-number": inPort,
2254 "error": err})
2255 return
2256 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302257 }
npujarec5762e2020-01-01 14:08:48 +05302258 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302260 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302261 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002262 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302263 log.Fields{
2264 "intf": Intf,
2265 "onu-id": onuID,
2266 "uni-id": uniID,
2267 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302268 return
2269 }
2270 updatedFlows = nil
2271 for _, flow := range *flowInfo {
2272 updatedFlows = append(updatedFlows, flow)
2273 }
2274
2275 for i, storedFlow := range updatedFlows {
2276 if flow.Id == storedFlow.LogicalFlowID {
2277 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002279 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2281 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002282 return
2283 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002285 "flow-id": flow.Id,
2286 "stored-flow": storedFlow,
2287 "device-id": f.deviceHandler.device.Id,
2288 "stored-flow-id": flowID,
2289 "onu-id": onuID,
2290 "intf": Intf,
2291 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002292 //Remove the Flow from FlowInfo
2293 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2294 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2295 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002297 "flow-id": flow.Id,
2298 "stored-flow": storedFlow,
2299 "device-id": f.deviceHandler.device.Id,
2300 "stored-flow-id": flowID,
2301 "onu-id": onuID,
2302 "intf": Intf,
2303 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302304 return
2305 }
2306 }
2307 }
2308 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002309}
2310
Esin Karamanccb714b2019-11-29 15:02:06 +00002311//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
2312// clears resources reserved for this multicast flow
npujarec5762e2020-01-01 14:08:48 +05302313func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002314 classifierInfo := make(map[string]interface{})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
Esin Karaman65409d82020-03-18 10:58:18 +00002316 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002317
2318 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002319 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002320 return
2321 }
2322
Esin Karamanccb714b2019-11-29 15:02:06 +00002323 var onuID = int32(NoneOnuID)
2324 var uniID = int32(NoneUniID)
2325 var flowID uint32
2326 var updatedFlows []rsrcMgr.FlowInfo
2327
npujarec5762e2020-01-01 14:08:48 +05302328 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002329
2330 for _, flowID = range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302331 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002332 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302334 log.Fields{
2335 "intf": networkInterfaceID,
2336 "onu-id": onuID,
2337 "uni-id": uniID,
2338 "flow-id": flowID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002339 continue
2340 }
2341 updatedFlows = nil
2342 for _, flow := range *flowInfo {
2343 updatedFlows = append(updatedFlows, flow)
2344 }
2345 for i, storedFlow := range updatedFlows {
2346 if flow.Id == storedFlow.LogicalFlowID {
2347 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302349 log.Fields{
2350 "flow": storedFlow,
2351 "flow-id": flow.Id,
2352 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002353 //remove from device
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002355 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002356 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002357 log.Fields{
2358 "flow-id": flow.Id,
2359 "error": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002360 return
2361 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002363 //Remove the Flow from FlowInfo
2364 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
npujarec5762e2020-01-01 14:08:48 +05302365 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002366 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302367 log.Fields{"flow": storedFlow,
2368 "err": err})
Esin Karamanccb714b2019-11-29 15:02:06 +00002369 return
2370 }
2371 //release flow id
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Debugw(ctx, "releasing-multicast-flow-id",
Shrey Baid26912972020-04-16 21:02:31 +05302373 log.Fields{"flow-id": flowID,
2374 "interfaceID": networkInterfaceID})
npujarec5762e2020-01-01 14:08:48 +05302375 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00002376 }
2377 }
2378 }
2379}
2380
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002381//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002382func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302384 var direction string
2385 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002386
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302387 for _, action := range flows.GetActions(flow) {
2388 if action.Type == flows.OUTPUT {
2389 if out := action.GetOutput(); out != nil {
2390 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302392 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002394 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002395 }
2396 }
2397 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002398
2399 if flows.HasGroup(flow) {
2400 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002401 f.clearFlowFromResourceManager(ctx, flow, direction)
2402 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002403 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302404 direction = Upstream
2405 } else {
2406 direction = Downstream
2407 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302408
Neha Sharma96b7bf22020-06-15 10:37:32 +00002409 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002410 if err != nil {
2411 return err
2412 }
2413
2414 userKey := tpLockKey{intfID, onuID, uniID}
2415
2416 // Serialize flow removes on a per subscriber basis
2417 if f.perUserFlowHandleLock.TryLock(userKey) {
2418 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2419 f.perUserFlowHandleLock.Unlock(userKey)
2420 } else {
2421 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002423 return errors.New("failed-to-acquire-per-user-lock")
2424 }
2425
2426 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002427}
2428
Girish Gowdra3d633032019-12-10 16:37:05 +05302429func (f *OpenOltFlowMgr) waitForFlowDeletesToCompleteForOnu(ctx context.Context, intfID uint32, onuID uint32,
2430 uniID uint32, ch chan bool) {
2431 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2432 for {
2433 select {
2434 case <-time.After(20 * time.Millisecond):
2435 if flowDelRefCnt, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok || flowDelRefCnt == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debug(ctx, "pending-flow-deletes-completed")
Girish Gowdra3d633032019-12-10 16:37:05 +05302437 ch <- true
2438 return
2439 }
2440 case <-ctx.Done():
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Error(ctx, "flow-delete-wait-handler-routine-canceled")
Girish Gowdra3d633032019-12-10 16:37:05 +05302442 return
2443 }
2444 }
2445}
2446
Esin Karamanae41e2b2019-12-17 18:13:13 +00002447//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2448func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2449 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2450 if ethType, ok := classifierInfo[EthType]; ok {
2451 if ethType.(uint32) == IPv4EthType {
2452 if ipProto, ok := classifierInfo[IPProto]; ok {
2453 if ipProto.(uint32) == IgmpProto {
2454 return true
2455 }
2456 }
2457 }
2458 }
2459 }
2460 return false
2461}
2462
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002463// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302464// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002465func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002466 classifierInfo := make(map[string]interface{})
2467 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002468 var UsMeterID uint32
2469 var DsMeterID uint32
2470
Neha Sharma96b7bf22020-06-15 10:37:32 +00002471 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302472 log.Fields{
2473 "flow": flow,
2474 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002476
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002478 if err != nil {
2479 // Error logging is already done in the called function
2480 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002481 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302482 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002483
Esin Karamanccb714b2019-11-29 15:02:06 +00002484 if flows.HasGroup(flow) {
2485 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002486 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002487 }
2488
manikkaraj k17652a72019-05-06 09:06:36 -04002489 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002490 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002491 if err != nil {
2492 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002493 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002494 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002495
Neha Sharma96b7bf22020-06-15 10:37:32 +00002496 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302497 log.Fields{
2498 "classifierinfo_inport": classifierInfo[InPort],
2499 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002500 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002501
Humera Kouser94d7a842019-08-25 19:04:32 -04002502 if ethType, ok := classifierInfo[EthType]; ok {
2503 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002505 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002506 }
2507 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002508 if ipProto, ok := classifierInfo[IPProto]; ok {
2509 if ipProto.(uint32) == IPProtoDhcp {
2510 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302511 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002512 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002513 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002514 }
2515 }
2516 }
2517 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002518 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002519 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002520 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002521 }
A R Karthick1f85b802019-10-11 05:06:05 +00002522
Neha Sharma96b7bf22020-06-15 10:37:32 +00002523 f.deviceHandler.AddUniPortToOnu(ctx, intfID, onuID, portNo)
npujarec5762e2020-01-01 14:08:48 +05302524 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002525
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002527 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302528 return olterrors.NewErrNotFound("tpid-for-flow",
2529 log.Fields{
2530 "flow": flow,
2531 "intf-id": IntfID,
2532 "onu-id": onuID,
2533 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302536 log.Fields{
2537 "tp-id": TpID,
2538 "intf-id": intfID,
2539 "onu-id": onuID,
2540 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002541 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002542 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002543 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002544 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002545 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002546 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002547
2548 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302549
2550 pnFlDelKey := pendingFlowDeleteKey{intfID, onuID, uniID}
2551 if _, ok := f.pendingFlowDelete.Load(pnFlDelKey); !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002552 logger.Debugw(ctx, "no-pending-flows-found--going-ahead-with-flow-install",
Shrey Baid26912972020-04-16 21:02:31 +05302553 log.Fields{
2554 "intf-id": intfID,
2555 "onu-id": onuID,
2556 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302557 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302558 } else {
Girish Gowdra3d633032019-12-10 16:37:05 +05302559 pendingFlowDelComplete := make(chan bool)
2560 go f.waitForFlowDeletesToCompleteForOnu(ctx, intfID, onuID, uniID, pendingFlowDelComplete)
2561 select {
2562 case <-pendingFlowDelComplete:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002563 logger.Debugw(ctx, "all-pending-flow-deletes-completed",
Shrey Baid26912972020-04-16 21:02:31 +05302564 log.Fields{
2565 "intf-id": intfID,
2566 "onu-id": onuID,
2567 "uni-id": uniID})
npujarec5762e2020-01-01 14:08:48 +05302568 f.divideAndAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +05302569
2570 case <-time.After(10 * time.Second):
Shrey Baid26912972020-04-16 21:02:31 +05302571 return olterrors.NewErrTimeout("pending-flow-deletes",
2572 log.Fields{
2573 "intf-id": intfID,
2574 "onu-id": onuID,
2575 "uni-id": uniID}, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +05302576 }
2577 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002578 return nil
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002579}
2580
Esin Karamanccb714b2019-11-29 15:02:06 +00002581// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002582func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002583 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302585 "classifier-info": classifierInfo,
2586 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002587
Esin Karaman65409d82020-03-18 10:58:18 +00002588 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002589 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002590 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002591 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002592 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2593 //otherwise, classification is based on ipv4_dst by default.
2594 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2595 mcastFlowClassificationByEthDst := false
2596
2597 if mcastFlowClassificationByEthDst {
2598 //replace ipDst with ethDst
2599 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2600 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2601 // replace ipv4_dst classifier with eth_dst
2602 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2603 delete(classifierInfo, Ipv4Dst)
2604 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002605 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302606 log.Fields{
2607 "ip:": ipv4Dst.(uint32),
2608 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002609 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002610 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002611 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002612
David K. Bainbridge794735f2020-02-11 21:01:37 -08002613 onuID := NoneOnuID
2614 uniID := NoneUniID
2615 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002616
Neha Sharma96b7bf22020-06-15 10:37:32 +00002617 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302618 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002619 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002620 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002621 }
npujarec5762e2020-01-01 14:08:48 +05302622 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002623 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302624 return olterrors.NewErrNotFound("multicast-flow-id",
2625 log.Fields{
2626 "interface-id": networkInterfaceID,
2627 "onu-id": onuID,
2628 "uni-id": uniID,
2629 "gem-port-id": gemPortID,
2630 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002632 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002633 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2634 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002635 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002636 }
2637 groupID := actionInfo[GroupID].(uint32)
2638 multicastFlow := openoltpb2.Flow{
2639 FlowId: flowID,
2640 FlowType: Multicast,
2641 NetworkIntfId: int32(networkInterfaceID),
2642 GroupId: groupID,
2643 Classifier: classifierProto,
2644 Priority: int32(flow.Priority),
2645 Cookie: flow.Cookie}
2646
David K. Bainbridge794735f2020-02-11 21:01:37 -08002647 if err = f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002648 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002649 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002650 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651 //get cached group
2652 group, _, err := f.GetFlowGroupFromKVStore(ctx, groupID, true)
2653 if err == nil {
2654 //calling groupAdd to set group members after multicast flow creation
Andrea Campanellac63bba92020-03-10 17:01:04 +01002655 if err = f.ModifyGroup(ctx, group); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 //cached group can be removed now
2657 f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true)
Andrea Campanellac63bba92020-03-10 17:01:04 +01002658 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002660 }
2661 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662
2663 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2664 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2665 int32(onuID),
2666 int32(uniID),
2667 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002668 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002669 }
2670 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002671}
2672
Esin Karaman65409d82020-03-18 10:58:18 +00002673//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2674func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2675 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002676 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002677 if err != nil {
2678 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2679 }
2680 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002681 }
Esin Karaman65409d82020-03-18 10:58:18 +00002682 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302683 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002684 if e == nil && len(nniPorts) > 0 {
2685 return nniPorts[0], nil
2686 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302687 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002688}
2689
2690// AddGroup add or update the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002691func (f *OpenOltFlowMgr) AddGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002692 logger.Infow(ctx, "add-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002693 if group == nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002695 }
2696
2697 groupToOlt := openoltpb2.Group{
2698 GroupId: group.Desc.GroupId,
2699 Command: openoltpb2.Group_SET_MEMBERS,
2700 Action: f.buildGroupAction(),
2701 }
2702
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Debugw(ctx, "sending-group-to-device", log.Fields{"groupToOlt": groupToOlt})
npujarec5762e2020-01-01 14:08:48 +05302704 _, err := f.deviceHandler.Client.PerformGroupOperation(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002705 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002706 return olterrors.NewErrAdapter("add-group-operation-failed", log.Fields{"groupToOlt": groupToOlt}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002707 }
2708 // group members not created yet. So let's store the group
npujarec5762e2020-01-01 14:08:48 +05302709 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, true); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002710 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002711 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002712 logger.Infow(ctx, "add-group-operation-performed-on-the-device-successfully ", log.Fields{"groupToOlt": groupToOlt})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002713 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002714}
2715
2716//buildGroupAction creates and returns a group action
2717func (f *OpenOltFlowMgr) buildGroupAction() *openoltpb2.Action {
2718 var actionCmd openoltpb2.ActionCmd
2719 var action openoltpb2.Action
2720 action.Cmd = &actionCmd
2721 //pop outer vlan
2722 action.Cmd.RemoveOuterTag = true
2723 return &action
2724}
2725
2726// ModifyGroup updates the group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002727func (f *OpenOltFlowMgr) ModifyGroup(ctx context.Context, group *ofp.OfpGroupEntry) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Infow(ctx, "modify-group", log.Fields{"group": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002729 if group == nil || group.Desc == nil {
Jonathan Hartc4b19112020-04-02 11:21:45 -07002730 return olterrors.NewErrInvalidValue(log.Fields{"group": group}, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002731 }
2732
Neha Sharma96b7bf22020-06-15 10:37:32 +00002733 newGroup := f.buildGroup(ctx, group.Desc.GroupId, group.Desc.Buckets)
Esin Karamanccb714b2019-11-29 15:02:06 +00002734 //get existing members of the group
npujarec5762e2020-01-01 14:08:48 +05302735 val, groupExists, err := f.GetFlowGroupFromKVStore(ctx, group.Desc.GroupId, false)
Esin Karamanccb714b2019-11-29 15:02:06 +00002736
2737 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002738 return olterrors.NewErrNotFound("flow-group-in-kv-store", log.Fields{"groupId": group.Desc.GroupId}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002739 }
2740
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002741 var current *openoltpb2.Group // represents the group on the device
Esin Karamanccb714b2019-11-29 15:02:06 +00002742 if groupExists {
2743 // group already exists
Neha Sharma96b7bf22020-06-15 10:37:32 +00002744 current = f.buildGroup(ctx, group.Desc.GroupId, val.Desc.GetBuckets())
2745 logger.Debugw(ctx, "modify-group--group exists",
Shrey Baid26912972020-04-16 21:02:31 +05302746 log.Fields{
2747 "group on the device": val,
2748 "new": group})
Esin Karamanccb714b2019-11-29 15:02:06 +00002749 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002750 current = f.buildGroup(ctx, group.Desc.GroupId, nil)
Esin Karamanccb714b2019-11-29 15:02:06 +00002751 }
2752
Neha Sharma96b7bf22020-06-15 10:37:32 +00002753 logger.Debugw(ctx, "modify-group--comparing-current-and-new",
Shrey Baid26912972020-04-16 21:02:31 +05302754 log.Fields{
2755 "group on the device": current,
2756 "new": newGroup})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002757 // get members to be added
Andrea Campanellac63bba92020-03-10 17:01:04 +01002758 membersToBeAdded := f.findDiff(current, newGroup)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002759 // get members to be removed
Andrea Campanellac63bba92020-03-10 17:01:04 +01002760 membersToBeRemoved := f.findDiff(newGroup, current)
Esin Karamanccb714b2019-11-29 15:02:06 +00002761
Neha Sharma96b7bf22020-06-15 10:37:32 +00002762 logger.Infow(ctx, "modify-group--differences found", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302763 "membersToBeAdded": membersToBeAdded,
2764 "membersToBeRemoved": membersToBeRemoved,
2765 "groupId": group.Desc.GroupId})
Esin Karamanccb714b2019-11-29 15:02:06 +00002766
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002767 groupToOlt := openoltpb2.Group{
2768 GroupId: group.Desc.GroupId,
2769 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002770 var errAdd, errRemoved error
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002771 if membersToBeAdded != nil && len(membersToBeAdded) > 0 {
2772 groupToOlt.Command = openoltpb2.Group_ADD_MEMBERS
2773 groupToOlt.Members = membersToBeAdded
2774 //execute addMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002775 errAdd = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002776 }
2777 if membersToBeRemoved != nil && len(membersToBeRemoved) > 0 {
2778 groupToOlt.Command = openoltpb2.Group_REMOVE_MEMBERS
2779 groupToOlt.Members = membersToBeRemoved
2780 //execute removeMembers
Neha Sharma96b7bf22020-06-15 10:37:32 +00002781 errRemoved = f.callGroupAddRemove(ctx, &groupToOlt)
Esin Karamanccb714b2019-11-29 15:02:06 +00002782 }
2783
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002784 //save the modified group
Andrea Campanellac63bba92020-03-10 17:01:04 +01002785 if errAdd == nil && errRemoved == nil {
npujarec5762e2020-01-01 14:08:48 +05302786 if err := f.resourceMgr.AddFlowGroupToKVStore(ctx, group, false); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002787 return olterrors.NewErrPersistence("add", "flow-group", group.Desc.GroupId, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002788 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002789 logger.Infow(ctx, "modify-group-was-success--storing-group",
Shrey Baid26912972020-04-16 21:02:31 +05302790 log.Fields{
2791 "group": group,
2792 "existingGroup": current})
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002793 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794 logger.Warnw(ctx, "one-of-the-group-add/remove-operations-failed--cannot-save-group-modifications",
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002795 log.Fields{"group": group})
Andrea Campanellac63bba92020-03-10 17:01:04 +01002796 if errAdd != nil {
2797 return errAdd
2798 }
2799 return errRemoved
Esin Karamanccb714b2019-11-29 15:02:06 +00002800 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002801 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002802}
2803
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002804//callGroupAddRemove performs add/remove buckets operation for the indicated group
Neha Sharma96b7bf22020-06-15 10:37:32 +00002805func (f *OpenOltFlowMgr) callGroupAddRemove(ctx context.Context, group *openoltpb2.Group) error {
2806 if err := f.performGroupOperation(ctx, group); err != nil {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002807 st, _ := status.FromError(err)
2808 //ignore already exists error code
2809 if st.Code() != codes.AlreadyExists {
Andrea Campanellac63bba92020-03-10 17:01:04 +01002810 return olterrors.NewErrGroupOp("groupAddRemove", group.GroupId, log.Fields{"status": st}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002811 }
2812 }
Andrea Campanellac63bba92020-03-10 17:01:04 +01002813 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002814}
2815
2816//findDiff compares group members and finds members which only exists in groups2
2817func (f *OpenOltFlowMgr) findDiff(group1 *openoltpb2.Group, group2 *openoltpb2.Group) []*openoltpb2.GroupMember {
2818 var members []*openoltpb2.GroupMember
2819 for _, bucket := range group2.Members {
2820 if !f.contains(group1.Members, bucket) {
2821 // bucket does not exist and must be added
2822 members = append(members, bucket)
2823 }
2824 }
2825 return members
2826}
2827
2828//contains returns true if the members list contains the given member; false otherwise
2829func (f *OpenOltFlowMgr) contains(members []*openoltpb2.GroupMember, member *openoltpb2.GroupMember) bool {
2830 for _, groupMember := range members {
2831 if groupMember.InterfaceId == member.InterfaceId {
2832 return true
2833 }
2834 }
2835 return false
2836}
2837
Esin Karaman0ebd2a32020-02-09 18:45:36 +00002838//performGroupOperation call performGroupOperation operation of openolt proto
Neha Sharma96b7bf22020-06-15 10:37:32 +00002839func (f *OpenOltFlowMgr) performGroupOperation(ctx context.Context, group *openoltpb2.Group) error {
2840 logger.Debugw(ctx, "sending-group-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05302841 log.Fields{
2842 "groupToOlt": group,
2843 "command": group.Command})
Esin Karamanccb714b2019-11-29 15:02:06 +00002844 _, err := f.deviceHandler.Client.PerformGroupOperation(context.Background(), group)
2845 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002846 return olterrors.NewErrAdapter("group-operation-failed", log.Fields{"groupToOlt": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002847 }
Girish Kumarf26e4882020-03-05 06:49:10 +00002848 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002849}
2850
2851//buildGroup build openoltpb2.Group from given group id and bucket list
Neha Sharma96b7bf22020-06-15 10:37:32 +00002852func (f *OpenOltFlowMgr) buildGroup(ctx context.Context, groupID uint32, buckets []*ofp.OfpBucket) *openoltpb2.Group {
Esin Karamanccb714b2019-11-29 15:02:06 +00002853 group := openoltpb2.Group{
2854 GroupId: groupID}
2855 // create members of the group
2856 if buckets != nil {
2857 for _, ofBucket := range buckets {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002858 member := f.buildMember(ctx, ofBucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00002859 if member != nil && !f.contains(group.Members, member) {
2860 group.Members = append(group.Members, member)
2861 }
2862 }
2863 }
2864 return &group
2865}
2866
2867//buildMember builds openoltpb2.GroupMember from an OpenFlow bucket
Neha Sharma96b7bf22020-06-15 10:37:32 +00002868func (f *OpenOltFlowMgr) buildMember(ctx context.Context, ofBucket *ofp.OfpBucket) *openoltpb2.GroupMember {
Esin Karamanccb714b2019-11-29 15:02:06 +00002869 var outPort uint32
2870 outPortFound := false
2871 for _, ofAction := range ofBucket.Actions {
2872 if ofAction.Type == ofp.OfpActionType_OFPAT_OUTPUT {
2873 outPort = ofAction.GetOutput().Port
2874 outPortFound = true
2875 }
2876 }
2877
2878 if !outPortFound {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002879 logger.Debugw(ctx, "bucket-skipped-since-no-out-port-found-in-it", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002880 return nil
2881 }
2882 interfaceID := IntfIDFromUniPortNum(outPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002883 logger.Debugw(ctx, "got-associated-interface-id-of-the-port",
Shrey Baid26912972020-04-16 21:02:31 +05302884 log.Fields{
2885 "portNumber:": outPort,
2886 "interfaceId:": interfaceID})
Esin Karamanccb714b2019-11-29 15:02:06 +00002887 if groupInfo, ok := f.interfaceToMcastQueueMap[interfaceID]; ok {
2888 member := openoltpb2.GroupMember{
2889 InterfaceId: interfaceID,
2890 InterfaceType: openoltpb2.GroupMember_PON,
2891 GemPortId: groupInfo.gemPortID,
2892 Priority: groupInfo.servicePriority,
2893 }
2894 //add member to the group
2895 return &member
2896 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Warnf(ctx, "bucket-skipped-since-interface-2-gem-mapping-cannot-be-found", log.Fields{"ofBucket": ofBucket})
Esin Karamanccb714b2019-11-29 15:02:06 +00002898 return nil
2899}
2900
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002901//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002902func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002903
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302905 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302907 log.Fields{
2908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002911 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302912 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002914
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002916 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002917 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
manikkaraj k17652a72019-05-06 09:06:36 -04002918 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(context.Background(),
2919 tpDownloadMsg,
2920 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302921 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002922 onuDev.deviceType,
2923 onuDev.deviceID,
2924 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002925 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302926 return olterrors.NewErrCommunication("send-techprofile-download-request",
2927 log.Fields{
2928 "from-adapter": f.deviceHandler.device.Type,
2929 "to-adapter": onuDev.deviceType,
2930 "onu-id": onuDev.deviceID,
2931 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002932 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002933 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302934 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302935}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002936
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302937//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002938func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302939
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002940 f.onuGemInfoLock[intfID].Lock()
2941 defer f.onuGemInfoLock[intfID].Unlock()
2942
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302943 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2944 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002945 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002946 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302947 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002948 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302949 log.Fields{
2950 "intf-id": intfID,
2951 "onu-id": onuID,
2952 "serial-num": serialNum,
2953 "onu": onu,
2954 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002955 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002956}
2957
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302959func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002960
2961 f.onuGemInfoLock[intfID].Lock()
2962 defer f.onuGemInfoLock[intfID].Unlock()
2963
Neha Sharma96b7bf22020-06-15 10:37:32 +00002964 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302965 log.Fields{
2966 "gem": gemPort,
2967 "intf": intfID,
2968 "onu": onuID,
2969 "device-id": f.deviceHandler.device.Id,
2970 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302971 onugem := f.onuGemInfo[intfID]
2972 // update the gem to the local cache as well as to kv strore
2973 for idx, onu := range onugem {
2974 if onu.OnuID == onuID {
2975 // check if gem already exists , else update the cache and kvstore
2976 for _, gem := range onu.GemPorts {
2977 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002978 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302979 log.Fields{
2980 "gem": gemPort,
2981 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302982 return
2983 }
2984 }
2985 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2986 f.onuGemInfo[intfID] = onugem
2987 }
2988 }
npujarec5762e2020-01-01 14:08:48 +05302989 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302990 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302992 log.Fields{
2993 "intf-id": intfID,
2994 "onu-id": onuID,
2995 "gemPort": gemPort,
2996 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002997 return
2998 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002999 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05303000 log.Fields{
3001 "gem": gemPort,
3002 "intf": intfID,
3003 "onu": onuID,
3004 "device-id": f.deviceHandler.device.Id,
3005 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003006}
3007
3008// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003009
3010//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303012
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003013 f.onuGemInfoLock[intfID].Lock()
3014 defer f.onuGemInfoLock[intfID].Unlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303015
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05303017 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003018 "device-id": f.deviceHandler.device.Id,
3019 "onu-geminfo": f.onuGemInfo[intfID],
3020 "intf-id": intfID,
3021 "gemport-id": gemPortID})
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003022
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303023 // get onuid from the onugem info cache
3024 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07003025
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303026 for _, onu := range onugem {
3027 for _, gem := range onu.GemPorts {
3028 if gem == gemPortID {
3029 return onu.OnuID, nil
3030 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003031 }
3032 }
Thomas Lee S94109f12020-03-03 16:39:29 +05303033 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003034 "interface-id": intfID,
3035 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00003036 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003037}
3038
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003039//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05303040func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003041 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003042 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003043 var err error
3044
3045 if packetIn.IntfType == "pon" {
3046 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003048 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003049 return logicalPortNum, err
3050 }
3051 if packetIn.PortNo != 0 {
3052 logicalPortNum = packetIn.PortNo
3053 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003054 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003056 }
3057 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
npujarec5762e2020-01-01 14:08:48 +05303058 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003059 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003060 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003061 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05303063 log.Fields{
3064 "logical-port-num": logicalPortNum,
3065 "intf-type": packetIn.IntfType,
3066 "packet": hex.EncodeToString(packetIn.Pkt),
3067 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003068 return logicalPortNum, nil
3069}
3070
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003071//GetPacketOutGemPortID returns gemPortId
npujarec5762e2020-01-01 14:08:48 +05303072func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003073 var gemPortID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003074 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303075
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003076 f.onuGemInfoLock[intfID].Lock()
3077 defer f.onuGemInfoLock[intfID].Unlock()
3078
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303079 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum}
3080
3081 gemPortID, ok := f.packetInGemPort[pktInkey]
3082 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05303084 log.Fields{
3085 "pktinkey": pktInkey,
3086 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303087 return gemPortID, err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003088 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303089 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
npujarec5762e2020-01-01 14:08:48 +05303090 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303091 if err == nil {
3092 if gemPortID != 0 {
3093 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05303095 log.Fields{
3096 "pktinkey": pktInkey,
3097 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303098 return gemPortID, nil
3099 }
3100 }
Shrey Baid26912972020-04-16 21:02:31 +05303101 return uint32(0), olterrors.NewErrNotFound("gem-port",
3102 log.Fields{
3103 "pktinkey": pktInkey,
3104 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003105}
3106
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003107// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303108func installFlowOnAllGemports(ctx context.Context,
3109 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003110 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003111 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05303112 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05303113 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303114 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003115 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04003116 args map[string]uint32,
3117 classifier map[string]interface{}, action map[string]interface{},
3118 logicalFlow *ofp.OfpFlowStats,
3119 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003120 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04003121 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00003122 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003123 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05303126 log.Fields{
3127 "FlowType": FlowType,
3128 "gemPorts": gemPorts,
3129 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05303130
Gamze Abaka724d0852020-03-18 12:10:24 +00003131 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
3132 // We need to trim prefix "0b", before further processing
3133 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
3134 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
3135
3136 // If a particular character in the string is set to '1', identify the index of this character from
3137 // the LSB position which marks the PCP bit consumed by the given gem port.
3138 // This PCP bit now becomes a classifier in the flow.
3139
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003140 switch TpInst := TpInst.(type) {
3141 case *tp.TechProfile:
3142 attributes := TpInst.DownstreamGemPortAttributeList
3143 if direction == Upstream {
3144 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00003145 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003146
3147 for _, gemPortAttribute := range attributes {
3148 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
3149 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00003150 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003151 gemPortID := gemPortAttribute.GemportID
3152 if allPbitsMarked(gemPortAttribute.PbitMap) {
3153 classifier[VlanPcp] = uint32(VlanPCPMask)
3154 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3155 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3156 } else if FlowType == EapolFlow {
3157 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3158 }
3159 } else {
3160 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
3161 if pbitSet == BinaryBit1 {
3162 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3163 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3164 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3165 } else if FlowType == EapolFlow {
3166 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3167 }
3168 }
3169 }
3170 }
3171 }
3172 case *tp.EponProfile:
3173 if direction == Upstream {
3174 attributes := TpInst.UpstreamQueueAttributeList
3175 for _, queueAttribute := range attributes {
3176 gemPortID := queueAttribute.GemportID
3177 if allPbitsMarked(queueAttribute.PbitMap) {
3178 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00003179 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003180 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003181 } else if FlowType == EapolFlow {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003182 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
Gamze Abaka724d0852020-03-18 12:10:24 +00003183 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003184 } else {
3185 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3186 if pbitSet == BinaryBit1 {
3187 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3188 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3189 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3190 } else if FlowType == EapolFlow {
3191 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3192 }
3193 }
3194 }
3195 }
3196 }
3197 } else {
3198 attributes := TpInst.DownstreamQueueAttributeList
3199 for _, queueAttribute := range attributes {
3200 gemPortID := queueAttribute.GemportID
3201 if allPbitsMarked(queueAttribute.PbitMap) {
3202 classifier[VlanPcp] = uint32(VlanPCPMask)
3203 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3204 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3205 } else if FlowType == EapolFlow {
3206 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3207 }
3208 } else {
3209 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
3210 if pbitSet == BinaryBit1 {
3211 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
3212 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
3213 f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID)
3214 } else if FlowType == EapolFlow {
3215 f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID)
3216 }
3217 }
3218 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05303219 }
3220 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04003221 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003222 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003223 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04003224 }
3225}
3226
Gamze Abaka724d0852020-03-18 12:10:24 +00003227func allPbitsMarked(pbitMap string) bool {
3228 for pos, pBit := range pbitMap {
3229 if pos >= 2 && pBit != BinaryBit1 {
3230 return false
3231 }
3232 }
3233 return true
3234}
3235
David K. Bainbridge794735f2020-02-11 21:01:37 -08003236func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003238 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003239 classifier[PacketTagType] = DoubleTag
3240 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003241 /* We manage flowId resource pool on per PON port basis.
3242 Since this situation is tricky, as a hack, we pass the NNI port
3243 index (network_intf_id) as PON port Index for the flowId resource
3244 pool. Also, there is no ONU Id available for trapping DHCP packets
3245 on NNI port, use onu_id as -1 (invalid)
3246 ****************** CAVEAT *******************
3247 This logic works if the NNI Port Id falls within the same valid
3248 range of PON Port Ids. If this doesn't work for some OLT Vendor
3249 we need to have a re-look at this.
3250 *********************************************
3251 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003252 onuID := -1
3253 uniID := -1
3254 gemPortID := -1
3255 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303257 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303258 return olterrors.NewErrNotFound("nni-intreface-id",
3259 log.Fields{
3260 "classifier": classifier,
3261 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003262 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303263 }
3264
Neha Sharma96b7bf22020-06-15 10:37:32 +00003265 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303266 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003267 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003268 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003269 }
Gamze Abaka724d0852020-03-18 12:10:24 +00003270 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003271 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303272 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
3273 log.Fields{
3274 "interface-id": networkInterfaceID,
3275 "onu-id": onuID,
3276 "uni-id": uniID,
3277 "gem-port-id": gemPortID,
3278 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003279 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003280 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003281 classifierProto, err := makeOpenOltClassifierField(classifier)
3282 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003283 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003284 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003285 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003286 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003287 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003288 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003289 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003290 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003291 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3292 OnuId: int32(onuID), // OnuId not required
3293 UniId: int32(uniID), // UniId not used
3294 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07003295 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07003296 AllocId: int32(allocID), // AllocId not used
3297 NetworkIntfId: int32(networkInterfaceID),
3298 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003299 Classifier: classifierProto,
3300 Action: actionProto,
3301 Priority: int32(logicalFlow.Priority),
3302 Cookie: logicalFlow.Cookie,
3303 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003304 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003305 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003306 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003307 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003308 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3309 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3310 int32(onuID),
3311 int32(uniID),
3312 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003313 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003314 }
3315 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003316}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003317
Esin Karamanae41e2b2019-12-17 18:13:13 +00003318//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3319func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3320 var packetType string
3321 ovid, ivid := false, false
3322 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3323 vid := vlanID & VlanvIDMask
3324 if vid != ReservedVlan {
3325 ovid = true
3326 }
3327 }
3328 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3329 vid := uint32(metadata)
3330 if vid != ReservedVlan {
3331 ivid = true
3332 }
3333 }
3334 if ovid && ivid {
3335 packetType = DoubleTag
3336 } else if !ovid && !ivid {
3337 packetType = Untagged
3338 } else {
3339 packetType = SingleTag
3340 }
3341 return packetType
3342}
3343
3344//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003345func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003346 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003347 action := make(map[string]interface{})
3348 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3349 action[TrapToHost] = true
3350 /* We manage flowId resource pool on per PON port basis.
3351 Since this situation is tricky, as a hack, we pass the NNI port
3352 index (network_intf_id) as PON port Index for the flowId resource
3353 pool. Also, there is no ONU Id available for trapping packets
3354 on NNI port, use onu_id as -1 (invalid)
3355 ****************** CAVEAT *******************
3356 This logic works if the NNI Port Id falls within the same valid
3357 range of PON Port Ids. If this doesn't work for some OLT Vendor
3358 we need to have a re-look at this.
3359 *********************************************
3360 */
3361 onuID := -1
3362 uniID := -1
3363 gemPortID := -1
3364 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003365 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003366 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303367 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003368 "classifier": classifier,
3369 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003370 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003371 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003372 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303373 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003374 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003375 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003376 }
npujarec5762e2020-01-01 14:08:48 +05303377 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003378 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303379 return olterrors.NewErrNotFound("igmp-flow-id",
3380 log.Fields{
3381 "interface-id": networkInterfaceID,
3382 "onu-id": onuID,
3383 "uni-id": uniID,
3384 "gem-port-id": gemPortID,
3385 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003386 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003387 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003388 classifierProto, err := makeOpenOltClassifierField(classifier)
3389 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003390 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003392 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003393 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003394 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003395 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003396 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003397 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003398 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3399 OnuId: int32(onuID), // OnuId not required
3400 UniId: int32(uniID), // UniId not used
3401 FlowId: flowID,
3402 FlowType: Downstream,
3403 AllocId: int32(allocID), // AllocId not used
3404 NetworkIntfId: int32(networkInterfaceID),
3405 GemportId: int32(gemPortID), // GemportId not used
3406 Classifier: classifierProto,
3407 Action: actionProto,
3408 Priority: int32(logicalFlow.Priority),
3409 Cookie: logicalFlow.Cookie,
3410 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003411 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003412 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003413 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003414 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003415 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3416 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3417 int32(onuID),
3418 int32(uniID),
3419 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003420 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003421 }
3422 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003423}
3424
salmansiddiqui7ac62132019-08-22 03:58:50 +00003425func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3426 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303427 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003428 }
3429 if Dir == tp_pb.Direction_UPSTREAM {
3430 return "upstream", nil
3431 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3432 return "downstream", nil
3433 }
3434 return "", nil
3435}
3436
npujarec5762e2020-01-01 14:08:48 +05303437func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003438 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003439 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003440 var gemPort uint32
3441 intfID := args[IntfID]
3442 onuID := args[OnuID]
3443 uniID := args[UniID]
3444 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003445 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003446 if ipProto, ok := classifierInfo[IPProto]; ok {
3447 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003448 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003449 "tp-id": tpID,
3450 "alloc-id": allocID,
3451 "intf-id": intfID,
3452 "onu-id": onuID,
3453 "uni-id": uniID,
3454 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003455 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003456 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003457 tp_pb.Direction_UPSTREAM,
3458 pcp.(uint32))
3459 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003460
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003461 f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003462 } else {
3463 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003464 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003465 }
3466
Girish Gowdra32625212020-04-29 11:26:35 -07003467 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003468 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303469 log.Fields{
3470 "intf-id": intfID,
3471 "onu-id": onuID,
3472 "uni-id": uniID,
3473 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003474 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003475 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003476 tp_pb.Direction_UPSTREAM,
3477 pcp.(uint32))
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003478 f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003479 } else {
3480 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003481 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003482 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003483 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003484 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003485 return
3486 }
3487 } else if ethType, ok := classifierInfo[EthType]; ok {
3488 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003489 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003490 "intf-id": intfID,
3491 "onu-id": onuID,
3492 "uni-id": uniID,
3493 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003494 var vlanID uint32
3495 if val, ok := classifierInfo[VlanVid]; ok {
3496 vlanID = (val.(uint32)) & VlanvIDMask
3497 } else {
3498 vlanID = DefaultMgmtVlan
3499 }
3500 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003501 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003502 tp_pb.Direction_UPSTREAM,
3503 pcp.(uint32))
3504
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003505 f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003506 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003507 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003508 }
3509 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003510 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003511 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003512 "intf-id": intfID,
3513 "onu-id": onuID,
3514 "uni-id": uniID,
3515 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003516 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003517 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003518 tp_pb.Direction_UPSTREAM,
3519 pcp.(uint32))
3520 //Adding HSIA upstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003521 f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003522 } else {
3523 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003524 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003525 }
3526 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003527 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003528 "intf-id": intfID,
3529 "onu-id": onuID,
3530 "uni-id": uniID,
3531 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003532 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003533 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003534 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003535 pcp.(uint32))
3536 //Adding HSIA downstream flow
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003537 f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003538 } else {
3539 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003540 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003541 }
3542 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003543 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303544 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003545 "intf-id": intfID,
3546 "onu-id": onuID,
3547 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303548 "classifier": classifierInfo,
3549 "action": actionInfo,
3550 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003551 return
3552 }
3553 // Send Techprofile download event to child device in go routine as it takes time
Neha Sharma96b7bf22020-06-15 10:37:32 +00003554 go f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003555}
3556
Gamze Abakafee36392019-10-03 11:17:24 +00003557func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPK gemPortKey) bool {
3558 flowIDList := f.flowsUsedByGemPort[gemPK]
3559 if len(flowIDList) > 1 {
3560 return true
3561 }
3562 return false
3563}
3564
npujarec5762e2020-01-01 14:08:48 +05303565func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3566 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003567 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3568 for _, currentGemPort := range currentGemPorts {
3569 for _, tpGemPort := range tpGemPorts {
3570 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3571 return true, currentGemPort
3572 }
3573 }
3574 }
Girish Gowdra54934262019-11-13 14:19:55 +05303575 if tpInst.InstanceCtrl.Onu == "single-instance" {
3576 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
npujarec5762e2020-01-01 14:08:48 +05303577 f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID)
3578 f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID)
Girish Gowdra54934262019-11-13 14:19:55 +05303579
3580 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3581 // still be used on other uni ports.
3582 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3583 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003584 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003585 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303586 for i := 0; i < len(tpInstances); i++ {
3587 tpI := tpInstances[i]
3588 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303589 for _, tpGemPort := range tpGemPorts {
3590 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003591 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303592 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303593 }
3594 }
3595 }
3596 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003597 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003598 return false, 0
3599}
3600
Neha Sharma96b7bf22020-06-15 10:37:32 +00003601func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003602 for _, field := range flows.GetOfbFields(flow) {
3603 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003604 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003605 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003606 } else if field.Type == flows.ETH_DST {
3607 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003608 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003609 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003610 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003611 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003612 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003613 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003614 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003615 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303616 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003617 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003618 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003619 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003620 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003621 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003622 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003623 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003624 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003625 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003626 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003627 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003628 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003629 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003630 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003631 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003632 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003633 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003634 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003635 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003636 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003637 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003638 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003639 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003640 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003641 return
3642 }
3643 }
3644}
3645
Neha Sharma96b7bf22020-06-15 10:37:32 +00003646func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003647 for _, action := range flows.GetActions(flow) {
3648 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003649 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003650 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003651 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003652 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003653 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003654 }
Scott Baker355d1742019-10-24 10:57:52 -07003655 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003656 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003657 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003658 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003659 if out := action.GetPush(); out != nil {
3660 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003661 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003662 } else {
3663 actionInfo[PushVlan] = true
3664 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003665 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303666 log.Fields{
3667 "push-tpid": actionInfo[TPID].(uint32),
3668 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003669 }
3670 }
Scott Baker355d1742019-10-24 10:57:52 -07003671 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003672 if out := action.GetSetField(); out != nil {
3673 if field := out.GetField(); field != nil {
3674 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003675 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003677 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3678 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003679 }
3680 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003681 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003682 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003683 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003684 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003685 }
3686 }
3687 return nil
3688}
3689
Neha Sharma96b7bf22020-06-15 10:37:32 +00003690func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003691 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003692 fieldtype := ofbField.GetType()
3693 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003694 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3695 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003696 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003697 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003698 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003699 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003700 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3701 pcp := ofbField.GetVlanPcp()
3702 actionInfo[VlanPcp] = pcp
3703 log.Debugw("action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003704 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003705 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003706 }
3707 }
3708}
3709
Neha Sharma96b7bf22020-06-15 10:37:32 +00003710func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003711 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003712 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003713 } else {
3714 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003715 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003716 }
3717}
3718
Neha Sharma96b7bf22020-06-15 10:37:32 +00003719func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003720 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003721 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003722 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3723 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003724 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003725 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003726 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303727 log.Fields{
3728 "newinport": classifierInfo[InPort].(uint32),
3729 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003730 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303731 return olterrors.NewErrNotFound("child-in-port",
3732 log.Fields{
3733 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3734 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003735 }
3736 }
3737 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003738 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003739 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003740 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003741 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003742 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003743 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303744 log.Fields{
3745 "newoutport": actionInfo[Output].(uint32),
3746 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003747 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303748 return olterrors.NewErrNotFound("out-port",
3749 log.Fields{
3750 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3751 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003752 }
3753 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3754 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003755 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003756 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003757 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303758 log.Fields{
3759 "newinport": actionInfo[Output].(uint32),
3760 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003761 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303762 return olterrors.NewErrNotFound("nni-port",
3763 log.Fields{
3764 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3765 "in-port": classifierInfo[InPort].(uint32),
3766 "out-port": actionInfo[Output].(uint32),
3767 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003768 }
3769 }
3770 }
3771 return nil
3772}
Gamze Abakafee36392019-10-03 11:17:24 +00003773
Neha Sharma96b7bf22020-06-15 10:37:32 +00003774func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003775 /* Metadata 8 bytes:
3776 Most Significant 2 Bytes = Inner VLAN
3777 Next 2 Bytes = Tech Profile ID(TPID)
3778 Least Significant 4 Bytes = Port ID
3779 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3780 subscriber related flows.
3781 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003782 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003783 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003784 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003785 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003786 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003787 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003788}
3789
3790func appendUnique(slice []uint32, item uint32) []uint32 {
3791 for _, sliceElement := range slice {
3792 if sliceElement == item {
3793 return slice
3794 }
3795 }
3796 return append(slice, item)
3797}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303798
3799// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003800func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303801
3802 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3803 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003804 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003805 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003806 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003807 log.Fields{
3808 "port-number": action[Output].(uint32),
3809 "error": err})
3810 return uint32(0), err
3811 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003812 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303813 return intfID, nil
3814 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003815 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003816 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003817 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003818 log.Fields{
3819 "port-number": action[Output].(uint32),
3820 "error": err})
3821 return uint32(0), err
3822 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003823 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303824 return intfID, nil
3825 }
3826 return uint32(0), nil
3827}
3828
3829// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
npujarec5762e2020-01-01 14:08:48 +05303830func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303831 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort}
3832
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003833 f.onuGemInfoLock[intfID].Lock()
3834 defer f.onuGemInfoLock[intfID].Unlock()
3835
Matt Jeanneret1719a072019-12-20 14:50:14 -05003836 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303837 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003838 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003839 logger.Infow(ctx, "pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
Shrey Baid26912972020-04-16 21:02:31 +05303840 log.Fields{
3841 "pktinkey": pktInkey,
3842 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003843 return
3844 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303845 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003846 f.packetInGemPort[pktInkey] = gemPort
3847
npujarec5762e2020-01-01 14:08:48 +05303848 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003849 logger.Infow(ctx, "pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05303850 log.Fields{
3851 "pktinkey": pktInkey,
3852 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303853 return
3854}
3855
3856// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303857func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003858
3859 f.onuGemInfoLock[intfID].Lock()
3860 defer f.onuGemInfoLock[intfID].Unlock()
3861
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303862 onugem := f.onuGemInfo[intfID]
3863 for idx, onu := range onugem {
3864 if onu.OnuID == onuID {
3865 for _, uni := range onu.UniPorts {
3866 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003867 logger.Infow(ctx, "uni-already-in-cache--no-need-to-update-cache-and-kv-store", log.Fields{"uni": portNum})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303868 return
3869 }
3870 }
3871 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3872 f.onuGemInfo[intfID] = onugem
3873 }
3874 }
npujarec5762e2020-01-01 14:08:48 +05303875 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303876}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303877
npujarec5762e2020-01-01 14:08:48 +05303878func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3879 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303880 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003881 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303882 return
3883 }
3884 for gem, FlowIDs := range flowIDsList {
3885 gemPK := gemPortKey{intf, uint32(gem)}
3886 f.flowsUsedByGemPort[gemPK] = FlowIDs
3887 }
3888 return
3889}
Esin Karamanccb714b2019-11-29 15:02:06 +00003890
3891//loadInterfaceToMulticastQueueMap reads multicast queues per interface from the KV store
3892//and put them into interfaceToMcastQueueMap.
npujarec5762e2020-01-01 14:08:48 +05303893func (f *OpenOltFlowMgr) loadInterfaceToMulticastQueueMap(ctx context.Context) {
3894 storedMulticastQueueMap, err := f.resourceMgr.GetMcastQueuePerInterfaceMap(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00003895 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003896 logger.Error(ctx, "failed-to-get-pon-interface-to-multicast-queue-map")
Esin Karamanccb714b2019-11-29 15:02:06 +00003897 return
3898 }
3899 for intf, queueInfo := range storedMulticastQueueMap {
3900 q := queueInfoBrief{
3901 gemPortID: queueInfo[0],
3902 servicePriority: queueInfo[1],
3903 }
3904 f.interfaceToMcastQueueMap[intf] = &q
3905 }
3906}
3907
3908//GetFlowGroupFromKVStore fetches and returns flow group from the KV store. Returns (nil, false, error) if any problem occurs during
3909//fetching the data. Returns (group, true, nil) if the group is fetched and returned successfully.
3910//Returns (nil, false, nil) if the group does not exists in the KV store.
npujarec5762e2020-01-01 14:08:48 +05303911func (f *OpenOltFlowMgr) GetFlowGroupFromKVStore(ctx context.Context, groupID uint32, cached bool) (*ofp.OfpGroupEntry, bool, error) {
3912 exists, groupInfo, err := f.resourceMgr.GetFlowGroupFromKVStore(ctx, groupID, cached)
Esin Karamanccb714b2019-11-29 15:02:06 +00003913 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003914 return nil, false, olterrors.NewErrNotFound("flow-group", log.Fields{"group-id": groupID}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00003915 }
3916 if exists {
3917 return newGroup(groupInfo.GroupID, groupInfo.OutPorts), exists, nil
3918 }
3919 return nil, exists, nil
3920}
3921
3922func newGroup(groupID uint32, outPorts []uint32) *ofp.OfpGroupEntry {
3923 groupDesc := ofp.OfpGroupDesc{
3924 Type: ofp.OfpGroupType_OFPGT_ALL,
3925 GroupId: groupID,
3926 }
3927 groupEntry := ofp.OfpGroupEntry{
3928 Desc: &groupDesc,
3929 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003930 for i := 0; i < len(outPorts); i++ {
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003931 var acts []*ofp.OfpAction
Esin Karamanccb714b2019-11-29 15:02:06 +00003932 acts = append(acts, flows.Output(outPorts[i]))
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003933 bucket := ofp.OfpBucket{
3934 Actions: acts,
3935 }
3936 groupDesc.Buckets = append(groupDesc.Buckets, &bucket)
Esin Karamanccb714b2019-11-29 15:02:06 +00003937 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003938 return &groupEntry
3939}