blob: 83da756add7286f639a6368801ca9adaa681d555 [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"
Esin Karamanccb714b2019-11-29 15:02:06 +000027 "github.com/opencord/voltha-lib-go/v3/pkg/flows"
28 "github.com/opencord/voltha-lib-go/v3/pkg/log"
29 tp "github.com/opencord/voltha-lib-go/v3/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080030 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Esin Karamanccb714b2019-11-29 15:02:06 +000031 "github.com/opencord/voltha-protos/v3/go/common"
32 ic "github.com/opencord/voltha-protos/v3/go/inter_container"
33 ofp "github.com/opencord/voltha-protos/v3/go/openflow_13"
34 openoltpb2 "github.com/opencord/voltha-protos/v3/go/openolt"
35 tp_pb "github.com/opencord/voltha-protos/v3/go/tech_profile"
36 "github.com/opencord/voltha-protos/v3/go/voltha"
Girish Gowdra9602eb42020-09-09 15:50:39 -070037 "math/big"
38 "strings"
39 "sync"
Chaitrashree G S579fe732019-08-20 20:50:47 -040040
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -040041 //deepcopy "github.com/getlantern/deepcopy"
Girish Gowdra3d633032019-12-10 16:37:05 +053042 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053043 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000044 "google.golang.org/grpc/codes"
45 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053046)
47
48const (
49 // Flow categories
manikkaraj kbf256be2019-03-25 00:13:48 +053050
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 //HsiaFlow flow category
52 HsiaFlow = "HSIA_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070054 //EapolFlow flow category
55 EapolFlow = "EAPOL_FLOW"
manikkaraj kbf256be2019-03-25 00:13:48 +053056
Manikkaraj kb1d51442019-07-23 10:41:02 -040057 //DhcpFlow flow category
58 DhcpFlow = "DHCP_FLOW"
59
Esin Karamanccb714b2019-11-29 15:02:06 +000060 //MulticastFlow flow category
61 MulticastFlow = "MULTICAST_FLOW"
62
Esin Karamanae41e2b2019-12-17 18:13:13 +000063 //IgmpFlow flow category
64 IgmpFlow = "IGMP_FLOW"
65
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070066 //IPProtoDhcp flow category
67 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053068
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 //IPProtoIgmp flow category
70 IPProtoIgmp = 2
71
72 //EapEthType eapethtype value
73 EapEthType = 0x888e
74 //LldpEthType lldp ethtype value
75 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000076 //IPv4EthType IPv4 ethernet type value
77 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078
79 //IgmpProto proto value
80 IgmpProto = 2
manikkaraj kbf256be2019-03-25 00:13:48 +053081
Andrea Campanella7acc0b92020-02-14 09:20:49 +010082 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
83 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085 //DefaultMgmtVlan default vlan value
86 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053087
manikkaraj kbf256be2019-03-25 00:13:48 +053088 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
David K. Bainbridge82efc492019-09-04 09:57:11 -070090 //Upstream constant
91 Upstream = "upstream"
92 //Downstream constant
93 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000094 //Multicast constant
95 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 //PacketTagType constant
97 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070098 //Untagged constant
99 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700100 //SingleTag constant
101 SingleTag = "single_tag"
102 //DoubleTag constant
103 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +0530104
105 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700106
107 //EthType constant
108 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +0000109 //EthDst constant
110 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 //TPID constant
112 TPID = "tpid"
113 //IPProto constant
114 IPProto = "ip_proto"
115 //InPort constant
116 InPort = "in_port"
117 //VlanVid constant
118 VlanVid = "vlan_vid"
119 //VlanPcp constant
120 VlanPcp = "vlan_pcp"
121
122 //UDPDst constant
123 UDPDst = "udp_dst"
124 //UDPSrc constant
125 UDPSrc = "udp_src"
126 //Ipv4Dst constant
127 Ipv4Dst = "ipv4_dst"
128 //Ipv4Src constant
129 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700130 //Metadata constant
131 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700132 //TunnelID constant
133 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700134 //Output constant
135 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000136 //GroupID constant
137 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700138 // Actions
139
140 //PopVlan constant
141 PopVlan = "pop_vlan"
142 //PushVlan constant
143 PushVlan = "push_vlan"
144 //TrapToHost constant
145 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400146 //MaxMeterBand constant
147 MaxMeterBand = 2
148 //VlanPCPMask contant
149 VlanPCPMask = 0xFF
150 //VlanvIDMask constant
151 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000152 //IntfID constant
153 IntfID = "intfId"
154 //OnuID constant
155 OnuID = "onuId"
156 //UniID constant
157 UniID = "uniId"
158 //PortNo constant
159 PortNo = "portNo"
160 //AllocID constant
161 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000162
163 //NoneOnuID constant
164 NoneOnuID = -1
165 //NoneUniID constant
166 NoneUniID = -1
167 //NoneGemPortID constant
168 NoneGemPortID = -1
Girish Gowdrafae935c2020-02-17 19:21:44 +0530169
170 // BinaryStringPrefix is binary string prefix
171 BinaryStringPrefix = "0b"
172 // BinaryBit1 is binary bit 1 expressed as a character
173 BinaryBit1 = '1'
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700174
175 // MapMutex
176 maxRetry = 300
177 maxDelay = 100000000
178 baseDelay = 10000000
179 factor = 1.1
180 jitter = 0.2
manikkaraj kbf256be2019-03-25 00:13:48 +0530181)
182
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400183type gemPortKey struct {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184 intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400185 gemPort uint32
186}
187
Girish Gowdra3d633032019-12-10 16:37:05 +0530188type tpLockKey struct {
189 intfID uint32
190 onuID uint32
191 uniID uint32
192}
193
Gamze Abakafee36392019-10-03 11:17:24 +0000194type schedQueue struct {
195 direction tp_pb.Direction
196 intfID uint32
197 onuID uint32
198 uniID uint32
199 tpID uint32
200 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700201 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000202 meterID uint32
203 flowMetadata *voltha.FlowMetadata
204}
205
Girish Gowdra9602eb42020-09-09 15:50:39 -0700206// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
207type pendingFlowRemoveDataKey struct {
208 intfID uint32
209 onuID uint32
210 uniID uint32
211}
212
213// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
214// This holds the number of pending flow removes and also a signal channel to
215// to indicate the receiver when all flow removes are handled
216type pendingFlowRemoveData struct {
217 pendingFlowRemoveCount uint32
218 allFlowsRemoved chan struct{}
Esin Karamanccb714b2019-11-29 15:02:06 +0000219}
220
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700221//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530222type OpenOltFlowMgr struct {
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000223 techprofile map[uint32]tp.TechProfileIf
Gamze Abakafee36392019-10-03 11:17:24 +0000224 deviceHandler *DeviceHandler
Girish Gowdra9602eb42020-09-09 15:50:39 -0700225 grpMgr *OpenOltGroupMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000226 resourceMgr *rsrcMgr.OpenOltResourceMgr
Gamze Abakafee36392019-10-03 11:17:24 +0000227 onuIdsLock sync.RWMutex
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700228 perGemPortLock *mapmutex.Mutex // lock to be used to access the flowsUsedByGemPort map
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 flowsUsedByGemPort map[gemPortKey][]uint32 //gem port id to flow ids
230 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700231 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700232 onuGemInfo map[uint32][]rsrcMgr.OnuGemInfo //onu, gem and uni info local cache, indexed by IntfId
233 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700234 onuGemInfoLock sync.RWMutex
Girish Gowdra3d633032019-12-10 16:37:05 +0530235 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 perUserFlowHandleLock *mapmutex.Mutex
237
238 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
239 // subscriber basis for the number of pending flow removes. This data is used
240 // to process all the flow removes for a subscriber before handling flow adds.
241 // Interleaving flow delete and flow add processing has known to cause PON resource
242 // management contentions on a per subscriber bases, so we need ensure ordering.
243 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
244 pendingFlowRemoveDataPerSubscriberLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530245}
246
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700247//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdra9602eb42020-09-09 15:50:39 -0700248func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000249 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530250 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 var err error
252 var idx uint32
253
manikkaraj kbf256be2019-03-25 00:13:48 +0530254 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700255 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530256 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000257 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000258 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
259 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530260 return nil
261 }
William Kurkian740a09c2019-10-23 17:07:38 -0400262 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdra9602eb42020-09-09 15:50:39 -0700263 flowMgr.pendingFlowRemoveDataPerSubscriberLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530264 flowMgr.flowsUsedByGemPort = make(map[gemPortKey][]uint32)
265 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530266 ponPorts := rMgr.DevInfo.GetPonPorts()
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700267 flowMgr.onuGemInfo = make(map[uint32][]rsrcMgr.OnuGemInfo, ponPorts)
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700268 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700269 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
270 flowMgr.perGemPortLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700271 flowMgr.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530272 //Load the onugem info cache from kv store on flowmanager start
273 for idx = 0; idx < ponPorts; idx++ {
npujarec5762e2020-01-01 14:08:48 +0530274 if flowMgr.onuGemInfo[idx], err = rMgr.GetOnuGemInfo(ctx, idx); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000275 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530276 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +0530277 //Load flowID list per gem map per interface from the kvstore.
npujarec5762e2020-01-01 14:08:48 +0530278 flowMgr.loadFlowIDlistForGem(ctx, idx)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530279 }
Esin Karamanccb714b2019-11-29 15:02:06 +0000280 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700281 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000282 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530283 return &flowMgr
284}
285
Kent Hagermane6ff1012020-07-14 15:07:53 -0400286func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000287 gemPK := gemPortKey{uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700288 if f.perGemPortLock.TryLock(gemPK) {
289 logger.Debugw(ctx, "registering-flow-for-device ",
290 log.Fields{
291 "flow": flowFromCore,
292 "device-id": f.deviceHandler.device.Id})
293 flowIDList, ok := f.flowsUsedByGemPort[gemPK]
294 if !ok {
295 flowIDList = []uint32{deviceFlow.FlowId}
296 }
297 flowIDList = appendUnique(flowIDList, deviceFlow.FlowId)
298 f.flowsUsedByGemPort[gemPK] = flowIDList
299
300 f.perGemPortLock.Unlock(gemPK)
301
302 // update the flowids for a gem to the KVstore
303 return f.resourceMgr.UpdateFlowIDsForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowIDList)
Gamze Abakafee36392019-10-03 11:17:24 +0000304 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700305 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
306 log.Fields{
307 "flow-from-core": flowFromCore,
308 "device-id": f.deviceHandler.device.Id,
309 "key": gemPK,
310 })
311 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
312 "flow-from-core": flowFromCore,
313 "device-id": f.deviceHandler.device.Id,
314 "key": gemPK,
315 }, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400316}
317
Girish Gowdra9602eb42020-09-09 15:50:39 -0700318func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000319 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200320 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000321 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530322 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700323 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530324
Neha Sharma96b7bf22020-06-15 10:37:32 +0000325 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530326 "device-id": f.deviceHandler.device.Id,
327 "intf-id": intfID,
328 "onu-id": onuID,
329 "uni-id": uniID,
330 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700331 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530332 "action": actionInfo,
333 "usmeter-iD": UsMeterID,
334 "dsmeter-iD": DsMeterID,
335 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400336 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
337 // is because the flow is an NNI flow and there would be no onu resources associated with it
338 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400339 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200340 cause := "no-onu-id-for-flow"
341 fields := log.Fields{
342 "onu": onuID,
343 "port-no": portNo,
344 "classifer": classifierInfo,
345 "action": actionInfo,
346 "device-id": f.deviceHandler.device.Id}
347 logger.Errorw(ctx, cause, fields)
348 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530349 }
350
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700351 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000352 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530353 "uni": uni,
354 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530355
356 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
357 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000358 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530359 "device-id": f.deviceHandler.device.Id,
360 "intf-id": intfID,
361 "onu-id": onuID,
362 "uni-id": uniID,
363 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700364 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530365 "action": actionInfo,
366 "usmeter-id": UsMeterID,
367 "dsmeter-id": DsMeterID,
368 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530369 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530370 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000371 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530372 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
Andrea Campanellabfe08432020-09-11 17:07:03 +0200373 return olterrors.NewErrNotFound(
374 "alloc-id-gem-ports-tp-unavailable",
375 nil, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +0530376 }
377 args := make(map[string]uint32)
378 args[IntfID] = intfID
379 args[OnuID] = onuID
380 args[UniID] = uniID
381 args[PortNo] = portNo
382 args[AllocID] = allocID
383
384 /* Flows can be added specific to gemport if p-bits are received.
385 * If no pbit mentioned then adding flows for all gemports
386 */
npujarec5762e2020-01-01 14:08:48 +0530387 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530388 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
389 } else {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200390 cause := "failed-to-acquire-per-user-flow-handle-lock"
391 fields := log.Fields{
392 "intf-id": intfID,
393 "onu-id": onuID,
394 "uni-id": uniID,
395 "flow-id": flow.Id,
396 "flow-cookie": flow.Cookie,
397 "device-id": f.deviceHandler.device.Id}
398 logger.Errorw(ctx, cause, fields)
399 return olterrors.NewErrAdapter(cause, fields, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 }
Andrea Campanellabfe08432020-09-11 17:07:03 +0200401 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530402}
403
salmansiddiqui7ac62132019-08-22 03:58:50 +0000404// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530405func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406
Neha Sharma96b7bf22020-06-15 10:37:32 +0000407 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530408 log.Fields{"dir": sq.direction,
409 "intf-id": sq.intfID,
410 "onu-id": sq.onuID,
411 "uni-id": sq.uniID,
412 "tp-id": sq.tpID,
413 "meter-id": sq.meterID,
414 "tp-inst": sq.tpInst,
415 "flowmetadata": sq.flowMetadata,
416 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417
Gamze Abakafee36392019-10-03 11:17:24 +0000418 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000419 if err != nil {
420 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421 }
422
423 /* Lets make a simple assumption that if the meter-id is present on the KV store,
424 * then the scheduler and queues configuration is applied on the OLT device
425 * in the given direction.
426 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000427
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530429 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530431 return olterrors.NewErrNotFound("meter",
432 log.Fields{"intf-id": sq.intfID,
433 "onu-id": sq.onuID,
434 "uni-id": sq.uniID,
435 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000437
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000439 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530443 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800444 "unsupported": "meter-id",
445 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "meter-id-in-flow": sq.meterID,
447 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000449
Neha Sharma96b7bf22020-06-15 10:37:32 +0000450 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530451 log.Fields{
452 "meter-id": sq.meterID,
453 "direction": Direction,
454 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455
Gamze Abakafee36392019-10-03 11:17:24 +0000456 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000457 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000458 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000459 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000461
462 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530463 return olterrors.NewErrNotFound("scheduler-config",
464 log.Fields{
465 "intf-id": sq.intfID,
466 "direction": sq.direction,
467 "tp-inst": sq.tpInst,
468 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469 }
470
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000472 if sq.flowMetadata != nil {
473 for _, meter := range sq.flowMetadata.Meters {
474 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530477 log.Fields{"meterConfig": meterConfig,
478 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 break
480 }
481 }
482 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000483 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 }
485 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530486 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800487 "reason": "Could-not-get-meterbands-from-flowMetadata",
488 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530489 "meter-id": sq.meterID,
490 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000492 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530493 log.Fields{"Bands": meterConfig.Bands,
494 "meter-id": sq.meterID,
495 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530496 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800497 "reason": "Invalid-number-of-bands-in-meter",
498 "meterband-count": len(meterConfig.Bands),
499 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530500 "meter-id": sq.meterID,
501 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 }
503 cir := meterConfig.Bands[0].Rate
504 cbs := meterConfig.Bands[0].BurstSize
505 eir := meterConfig.Bands[1].Rate
506 ebs := meterConfig.Bands[1].BurstSize
507 pir := cir + eir
508 pbs := cbs + ebs
509 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
510
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700511 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000512 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513
npujarec5762e2020-01-01 14:08:48 +0530514 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficShaping, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530515 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
516 log.Fields{"intf-id": sq.intfID,
517 "direction": sq.direction,
518 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400519 }
520
salmansiddiqui7ac62132019-08-22 03:58:50 +0000521 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400522 * store the meter id on the KV store, for further reference.
523 */
npujarec5762e2020-01-01 14:08:48 +0530524 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 +0530525 return olterrors.NewErrAdapter("failed-updating-meter-id",
526 log.Fields{"onu-id": sq.onuID,
527 "meter-id": sq.meterID,
528 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400529 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000530 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530531 log.Fields{"direction": Direction,
532 "Meter": meterConfig,
533 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400534 return nil
535}
536
npujarec5762e2020-01-01 14:08:48 +0530537func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficShaping *tp_pb.TrafficShapingInfo, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000538 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539
540 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530541 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
542 log.Fields{"intf-id": sq.intfID,
543 "direction": sq.direction,
544 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000545 }
546
Neha Sharma96b7bf22020-06-15 10:37:32 +0000547 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530548 log.Fields{
549 "direction": sq.direction,
550 "TrafficScheds": TrafficSched,
551 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530552 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553 IntfId: sq.intfID, OnuId: sq.onuID,
554 UniId: sq.uniID, PortNo: sq.uniPort,
555 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000556 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000557 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530559 "direction": sq.direction,
560 "traffic-queues": trafficQueues,
561 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562
563 // On receiving the CreateTrafficQueues request, the driver should create corresponding
564 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000565 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530566 log.Fields{"direction": sq.direction,
567 "traffic-queues": trafficQueues,
568 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530569 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
571 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000572 TrafficQueues: trafficQueues,
573 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530574 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530577 "direction": sq.direction,
578 "traffic-queues": trafficQueues,
579 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000580
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 //assumed that there is only one queue per PON for the multicast service
586 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
587 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700590 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000591 gemPortID: multicastQueuePerPonPort.GemportId,
592 servicePriority: multicastQueuePerPonPort.Priority,
593 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700594 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400596 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
597 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
598 return err
599 }
Shrey Baid26912972020-04-16 21:02:31 +0530600
Neha Sharma96b7bf22020-06-15 10:37:32 +0000601 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000602 }
603 }
604 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000605 return nil
606}
607
salmansiddiqui7ac62132019-08-22 03:58:50 +0000608// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530609func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610
611 var Direction string
612 var SchedCfg *tp_pb.SchedulerConfig
613 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000614 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530615 log.Fields{
616 "direction": sq.direction,
617 "intf-id": sq.intfID,
618 "onu-id": sq.onuID,
619 "uni-id": sq.uniID,
620 "uni-port": sq.uniPort,
621 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000622 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000623 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000625 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000626 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400627 Direction = "downstream"
628 }
629
Girish Kumar8f73fe02019-12-09 13:19:37 +0000630 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530631 return olterrors.NewErrNotFound("scheduler-config",
632 log.Fields{
633 "int-id": sq.intfID,
634 "direction": sq.direction,
635 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000636 }
637
npujarec5762e2020-01-01 14:08:48 +0530638 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530640 return olterrors.NewErrNotFound("meter",
641 log.Fields{
642 "onu-id": sq.onuID,
643 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400644 }
645 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530647 log.Fields{
648 "direction": Direction,
649 "intf-id": sq.intfID,
650 "onu-id": sq.onuID,
651 "uni-id": sq.uniID,
652 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653 return nil
654 }
655 cir := KVStoreMeter.Bands[0].Rate
656 cbs := KVStoreMeter.Bands[0].BurstSize
657 eir := KVStoreMeter.Bands[1].Rate
658 ebs := KVStoreMeter.Bands[1].BurstSize
659 pir := cir + eir
660 pbs := cbs + ebs
661
662 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
663
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700664 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000665 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000666
Neha Sharma96b7bf22020-06-15 10:37:32 +0000667 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000668 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530669 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
670 log.Fields{
671 "intf-id": sq.intfID,
672 "direction": sq.direction,
673 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000674 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675
npujarec5762e2020-01-01 14:08:48 +0530676 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000677 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
678 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000679 TrafficQueues: TrafficQueues,
680 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000681 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530682 log.Fields{
683 "intf-id": sq.intfID,
684 "traffic-queues": TrafficQueues,
685 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000687 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530688 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000689 IntfId: sq.intfID, OnuId: sq.onuID,
690 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000692 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530693 log.Fields{
694 "intf-id": sq.intfID,
695 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 }
697
Neha Sharma96b7bf22020-06-15 10:37:32 +0000698 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000699
700 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400701 * delete the meter id on the KV store.
702 */
npujarec5762e2020-01-01 14:08:48 +0530703 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400704 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530705 return olterrors.NewErrAdapter("unable-to-remove-meter",
706 log.Fields{
707 "onu": sq.onuID,
708 "meter": KVStoreMeter.MeterId,
709 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400710 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000711 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530712 log.Fields{
713 "meter-id": KVStoreMeter.MeterId,
714 "dir": Direction,
715 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400716 return err
717}
718
Gamze Abakafee36392019-10-03 11:17:24 +0000719// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700720func (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 +0000721 var allocIDs []uint32
722 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530723 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530724 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000725 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000726
npujarec5762e2020-01-01 14:08:48 +0530727 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
728 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400729
Neha Sharma96b7bf22020-06-15 10:37:32 +0000730 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530731
Neha Sharma96b7bf22020-06-15 10:37:32 +0000732 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530733 "intf-id": intfID,
734 "onu-id": onuID,
735 "uni-id": uniID,
736 "device-id": f.deviceHandler.device.Id,
737 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530738
Manikkaraj kb1d51442019-07-23 10:41:02 -0400739 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530740 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000741 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530743 log.Fields{
744 "path": tpPath,
745 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530746 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000747 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530748 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000749 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530750 log.Fields{
751 "error": err,
752 "tp-id": TpID,
753 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000754 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530755 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400756 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
757 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
758 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530759 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530761 log.Fields{
762 "uni": uni,
763 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530764 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530765 }
Gamze Abakafee36392019-10-03 11:17:24 +0000766
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700767 switch tpInst := techProfileInstance.(type) {
768 case *tp.TechProfile:
769 if UsMeterID != 0 {
770 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
771 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
772 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000773 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700774 log.Fields{
775 "error": err,
776 "meter-id": UsMeterID,
777 "device-id": f.deviceHandler.device.Id})
778 return 0, nil, nil
779 }
780 }
781 if DsMeterID != 0 {
782 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
783 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
784 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000785 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700786 log.Fields{
787 "error": err,
788 "meter-id": DsMeterID,
789 "device-id": f.deviceHandler.device.Id})
790 return 0, nil, nil
791 }
792 }
793 allocID := tpInst.UsScheduler.AllocID
794 for _, gem := range tpInst.UpstreamGemPortAttributeList {
795 gemPortIDs = append(gemPortIDs, gem.GemportID)
796 }
797 allocIDs = appendUnique(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000798
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700799 if tpInstanceExists {
800 return allocID, gemPortIDs, techProfileInstance
801 }
802
803 for _, gemPortID := range gemPortIDs {
804 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
805 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000806 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700807 log.Fields{
808 "alloc-ids": allocIDs,
809 "gemports": allgemPortIDs,
810 "device-id": f.deviceHandler.device.Id})
811 // Send Tconts and GEM ports to KV store
812 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530813 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700814 case *tp.EponProfile:
815 // CreateSchedulerQueues for EPON needs to be implemented here
816 // when voltha-protos for EPON is completed.
817 allocID := tpInst.AllocID
818 for _, gem := range tpInst.UpstreamQueueAttributeList {
819 gemPortIDs = append(gemPortIDs, gem.GemportID)
820 }
821 allocIDs = appendUnique(allocIDs, allocID)
822
823 if tpInstanceExists {
824 return allocID, gemPortIDs, techProfileInstance
825 }
826
827 for _, gemPortID := range gemPortIDs {
828 allgemPortIDs = appendUnique(allgemPortIDs, gemPortID)
829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000830 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700831 log.Fields{
832 "alloc-ids": allocIDs,
833 "gemports": allgemPortIDs,
834 "device-id": f.deviceHandler.device.Id})
835 // Send Tconts and GEM ports to KV store
836 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
837 return allocID, gemPortIDs, techProfileInstance
838 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000839 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700840 log.Fields{
841 "tpInst": tpInst})
842 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530843 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530844}
845
npujarec5762e2020-01-01 14:08:48 +0530846func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530847
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530849 log.Fields{
850 "intf-id": intfID,
851 "onu-id": onuID,
852 "uni-id": uniID,
853 "alloc-id": allocID,
854 "gemport-ids": gemPortIDs,
855 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530856 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530857 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000858 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 +0530859 }
npujarec5762e2020-01-01 14:08:48 +0530860 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000861 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 +0530862 }
npujarec5762e2020-01-01 14:08:48 +0530863 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000864 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 +0530865 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000866 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 -0400867 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530868 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400869 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530870}
871
Neha Sharma96b7bf22020-06-15 10:37:32 +0000872func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000873 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000875 for _, intfID := range techRange.IntfIds {
876 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[uint32(intfID)].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400877 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530879 log.Fields{
880 "intf-id": intfID,
881 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530882 }
883 }
884 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400885 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530886 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530887 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800888 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530889 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
890 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530891 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000892 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530893 log.Fields{
894 "numofTech": tpCount,
895 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
896 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530897 return nil
898}
899
npujarec5762e2020-01-01 14:08:48 +0530900func (f *OpenOltFlowMgr) addUpstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530901 portNo uint32, uplinkClassifier map[string]interface{},
902 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000903 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700904 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530906 log.Fields{
907 "uplinkClassifier": uplinkClassifier,
908 "uplinkAction": uplinkAction})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800909 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000910 Upstream, logicalFlow, allocID, gemportID, tpID)
Manikkaraj k884c1242019-04-11 16:26:42 +0530911 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530912}
913
npujarec5762e2020-01-01 14:08:48 +0530914func (f *OpenOltFlowMgr) addDownstreamDataFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530915 portNo uint32, downlinkClassifier map[string]interface{},
916 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000917 allocID uint32, gemportID uint32, tpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700918 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000919 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530920 log.Fields{
921 "downlinkClassifier": downlinkClassifier,
922 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400923 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
924 if vlan, exists := downlinkClassifier[VlanVid]; exists {
925 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700926 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000927 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
928 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530929 log.Fields{
930 "flow": logicalFlow,
931 "device-id": f.deviceHandler.device.Id,
932 "onu-id": onuID,
933 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800934 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400935 }
936 }
937 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530938 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400939
Manikkaraj k884c1242019-04-11 16:26:42 +0530940 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700941 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400942 // vlan_vid is a uint32. must be type asserted as such or conversion fails
943 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530944 if ok {
945 downlinkAction[VlanVid] = dlClVid & 0xfff
946 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530947 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530948 "reason": "failed-to-convert-vlanid-classifier",
949 "vlan-id": VlanVid,
950 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530951 }
952
David K. Bainbridge794735f2020-02-11 21:01:37 -0800953 return f.addHSIAFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000954 Downstream, logicalFlow, allocID, gemportID, tpID)
manikkaraj kbf256be2019-03-25 00:13:48 +0530955}
956
npujarec5762e2020-01-01 14:08:48 +0530957func (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 +0530958 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000959 allocID uint32, gemPortID uint32, tpID uint32) error {
Manikkaraj k884c1242019-04-11 16:26:42 +0530960 /* One of the OLT platform (Broadcom BAL) requires that symmetric
961 flows require the same flow_id to be used across UL and DL.
962 Since HSIA flow is the only symmetric flow currently, we need to
963 re-use the flow_id across both direction. The 'flow_category'
964 takes priority over flow_cookie to find any available HSIA_FLOW
965 id for the ONU.
966 */
Neha Sharma96b7bf22020-06-15 10:37:32 +0000967 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530968 log.Fields{
969 "intf-id": intfID,
970 "onu-id": onuID,
971 "uni-id": uniID,
972 "device-id": f.deviceHandler.device.Id,
973 "classifier": classifier,
974 "action": action,
975 "direction": direction,
976 "alloc-id": allocID,
977 "gemport-id": gemPortID,
978 "logicalflow": *logicalFlow})
Girish Gowdrafae935c2020-02-17 19:21:44 +0530979 var vlanPbit uint32 = 0xff // means no pbit
Gamze Abaka724d0852020-03-18 12:10:24 +0000980 var vlanVid uint32
Manikkaraj kb1d51442019-07-23 10:41:02 -0400981 if _, ok := classifier[VlanPcp]; ok {
Gamze Abakafee36392019-10-03 11:17:24 +0000982 vlanPbit = classifier[VlanPcp].(uint32)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 logger.Debugw(ctx, "found-pbit-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530984 log.Fields{
985 "vlan-pbit": vlanPbit,
986 "intf-id": intfID,
987 "onu-id": onuID,
988 "device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800989 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000990 logger.Debugw(ctx, "pbit-not-found-in-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530991 log.Fields{
992 "vlan-pcp": VlanPcp,
993 "intf-id": intfID,
994 "onu-id": onuID,
995 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400996 }
Gamze Abaka724d0852020-03-18 12:10:24 +0000997 if _, ok := classifier[VlanVid]; ok {
998 vlanVid = classifier[VlanVid].(uint32)
Girish Kumara1ea2aa2020-08-19 18:14:22 +0000999 logger.Debugw(ctx, "found-vlan-in-the-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301000 log.Fields{
1001 "vlan-vid": vlanVid,
1002 "intf-id": intfID,
1003 "onu-id": onuID,
1004 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001005 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001006 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301007 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001008 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301009 log.Fields{
1010 "device-id": f.deviceHandler.device.Id,
1011 "intf-id": intfID,
1012 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001013 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301014 }
Gamze Abaka724d0852020-03-18 12:10:24 +00001015 flowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, HsiaFlow, vlanVid, vlanPbit)
Manikkaraj k884c1242019-04-11 16:26:42 +05301016 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301017 return olterrors.NewErrNotFound("hsia-flow-id",
1018 log.Fields{
1019 "direction": direction,
1020 "device-id": f.deviceHandler.device.Id,
1021 "intf-id": intfID,
1022 "onu-id": onuID,
1023 }, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301024 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001025 classifierProto, err := makeOpenOltClassifierField(classifier)
1026 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301027 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301028 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301030 log.Fields{
1031 "classifier": *classifierProto,
1032 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001033 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001034 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301035 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301036 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301038 log.Fields{
1039 "action": *actionProto,
1040 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001041 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301042 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301043 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001044 log.Fields{
1045 "classifier": classifier,
1046 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301047 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001048 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301049 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001050 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
1051 OnuId: int32(onuID),
1052 UniId: int32(uniID),
salmansiddiqui7ac62132019-08-22 03:58:50 +00001053 FlowId: flowID,
Manikkaraj k884c1242019-04-11 16:26:42 +05301054 FlowType: direction,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 AllocId: int32(allocID),
1056 NetworkIntfId: int32(networkIntfID),
1057 GemportId: int32(gemPortID),
Manikkaraj k884c1242019-04-11 16:26:42 +05301058 Classifier: classifierProto,
1059 Action: actionProto,
1060 Priority: int32(logicalFlow.Priority),
1061 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001062 PortNo: portNo,
1063 TechProfileId: tpID,
1064 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301066 return olterrors.NewErrFlowOp("add", flowID, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301067 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001068 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301069 log.Fields{"direction": direction,
1070 "device-id": f.deviceHandler.device.Id,
1071 "flow": flow,
1072 "intf-id": intfID,
1073 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001074 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, HsiaFlow, flowID, logicalFlow.Id)
1075 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1076 flow.OnuId,
1077 flow.UniId,
1078 flow.FlowId /*flowCategory,*/, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301079 return olterrors.NewErrPersistence("update", "flow", flowID,
1080 log.Fields{
1081 "flow": flow,
1082 "device-id": f.deviceHandler.device.Id,
1083 "intf-id": intfID,
1084 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001085 }
1086 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301087}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001088
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001089func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1090 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1091 gemPortID uint32, tpID uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301092
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301094 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301095 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301097 "action": action,
1098 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301100 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301101
1102 // Clear the action map
1103 for k := range action {
1104 delete(action, k)
1105 }
1106
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001107 action[TrapToHost] = true
1108 classifier[UDPSrc] = uint32(68)
1109 classifier[UDPDst] = uint32(67)
1110 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301111
Neha Sharma96b7bf22020-06-15 10:37:32 +00001112 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301113 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001114 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301115 log.Fields{
1116 "device-id": f.deviceHandler.device.Id,
1117 "intf-id": intfID,
1118 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301120 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301121
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 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 +05301123
1124 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301125 return olterrors.NewErrNotFound("flow",
1126 log.Fields{
1127 "interface-id": intfID,
1128 "gem-port": gemPortID,
1129 "cookie": flowStoreCookie,
1130 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132 }
1133
Neha Sharma96b7bf22020-06-15 10:37:32 +00001134 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301135 log.Fields{
1136 "ul_classifier": classifier,
1137 "ul_action": action,
1138 "uplinkFlowId": flowID,
1139 "intf-id": intfID,
1140 "onu-id": onuID,
1141 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301142
David K. Bainbridge794735f2020-02-11 21:01:37 -08001143 classifierProto, err := makeOpenOltClassifierField(classifier)
1144 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301145 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001147 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001148 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301150 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301151 }
1152
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001154 OnuId: int32(onuID),
1155 UniId: int32(uniID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001157 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 AllocId: int32(allocID),
1159 NetworkIntfId: int32(networkIntfID),
1160 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301161 Classifier: classifierProto,
1162 Action: actionProto,
1163 Priority: int32(logicalFlow.Priority),
1164 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001165 PortNo: portNo,
1166 TechProfileId: tpID,
1167 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001168 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301169 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "device-id": f.deviceHandler.device.Id,
1174 "flow-id": flowID,
1175 "intf-id": intfID,
1176 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &dhcpFlow, flowStoreCookie, "DHCP", flowID, logicalFlow.Id)
1178 if err := f.updateFlowInfoToKVStore(ctx, dhcpFlow.AccessIntfId,
1179 dhcpFlow.OnuId,
1180 dhcpFlow.UniId,
1181 dhcpFlow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301182 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1183 log.Fields{
1184 "flow": dhcpFlow,
1185 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186 }
1187
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301189}
1190
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301192func (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 +00001193 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32) error {
1194 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, IgmpFlow, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195}
1196
1197//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301198func (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 +00001199 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, flowType string, tpID uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001200
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301203 return olterrors.NewErrNotFound("nni-interface-id",
1204 log.Fields{
1205 "classifier": classifier,
1206 "action": action,
1207 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001209 }
1210
1211 // Clear the action map
1212 for k := range action {
1213 delete(action, k)
1214 }
1215
1216 action[TrapToHost] = true
1217 classifier[PacketTagType] = SingleTag
1218 delete(classifier, VlanVid)
1219
Neha Sharma96b7bf22020-06-15 10:37:32 +00001220 flowStoreCookie := getFlowStoreCookie(ctx, classifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301221 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkIntfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001222 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001223 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001224 }
1225
npujarec5762e2020-01-01 14:08:48 +05301226 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 +00001227
1228 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301229 return olterrors.NewErrNotFound("flow-id",
1230 log.Fields{
1231 "intf-id": intfID,
1232 "oni-id": onuID,
1233 "cookie": flowStoreCookie,
1234 "flow-type": flowType,
1235 "device-id": f.deviceHandler.device.Id,
1236 "onu-id": onuID},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 }
1239
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301241 log.Fields{
1242 "ul_classifier": classifier,
1243 "ul_action": action,
1244 "uplinkFlowId": flowID,
1245 "flowType": flowType,
1246 "device-id": f.deviceHandler.device.Id,
1247 "intf-id": intfID,
1248 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 classifierProto, err := makeOpenOltClassifierField(classifier)
1251 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301252 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001254 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301255 log.Fields{
1256 "classifier": *classifierProto,
1257 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001258 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001259 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301260 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 }
1262
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 OnuId: int32(onuID),
1265 UniId: int32(uniID),
1266 FlowId: flowID,
1267 FlowType: Upstream,
1268 AllocId: int32(allocID),
1269 NetworkIntfId: int32(networkIntfID),
1270 GemportId: int32(gemPortID),
1271 Classifier: classifierProto,
1272 Action: actionProto,
1273 Priority: int32(logicalFlow.Priority),
1274 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001275 PortNo: portNo,
1276 TechProfileId: tpID,
1277 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001278
David K. Bainbridge794735f2020-02-11 21:01:37 -08001279 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301280 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 -08001281 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001282 logger.Infof(ctx, "%s ul-flow-added-to-device-successfully", flowType)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &flow, flowStoreCookie, flowType, flowID, logicalFlow.Id)
1285 if err := f.updateFlowInfoToKVStore(ctx, flow.AccessIntfId,
1286 flow.OnuId,
1287 flow.UniId,
1288 flow.FlowId, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301289 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 +00001290 }
1291
David K. Bainbridge794735f2020-02-11 21:01:37 -08001292 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293}
1294
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001296func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1297 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
1298 gemPortID uint32, vlanID uint32, tpID uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001299 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301300 log.Fields{
1301 "intf-id": intfID,
1302 "onu-id": onuID,
1303 "port-no": portNo,
1304 "alloc-id": allocID,
1305 "gemport-id": gemPortID,
1306 "vlan-id": vlanID,
1307 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301308
1309 uplinkClassifier := make(map[string]interface{})
1310 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301311
manikkaraj kbf256be2019-03-25 00:13:48 +05301312 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001313 uplinkClassifier[EthType] = uint32(EapEthType)
1314 uplinkClassifier[PacketTagType] = SingleTag
1315 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001316 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301317 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 uplinkAction[TrapToHost] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00001319 flowStoreCookie := getFlowStoreCookie(ctx, uplinkClassifier, gemPortID)
npujarec5762e2020-01-01 14:08:48 +05301320 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(intfID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301322 "device-id": f.deviceHandler.device.Id,
1323 "onu-id": onuID,
1324 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001325 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301326 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301327 //Add Uplink EAPOL Flow
Gamze Abaka724d0852020-03-18 12:10:24 +00001328 uplinkFlowID, err := f.resourceMgr.GetFlowID(ctx, intfID, int32(onuID), int32(uniID), gemPortID, flowStoreCookie, "", 0, 0)
manikkaraj kbf256be2019-03-25 00:13:48 +05301329 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301330 return olterrors.NewErrNotFound("flow-id",
1331 log.Fields{
1332 "intf-id": intfID,
1333 "onu-id": onuID,
1334 "coookie": flowStoreCookie,
1335 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301337 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001338 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301339 log.Fields{
1340 "ul_classifier": uplinkClassifier,
1341 "ul_action": uplinkAction,
1342 "uplinkFlowId": uplinkFlowID,
1343 "device-id": f.deviceHandler.device.Id,
1344 "intf-id": intfID,
1345 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301346
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1348 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301349 return olterrors.NewErrInvalidValue(log.Fields{
1350 "classifier": uplinkClassifier,
1351 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301352 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301354 log.Fields{
1355 "classifier": *classifierProto,
1356 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001357 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301359 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001361 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301362 log.Fields{
1363 "action": *actionProto,
1364 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001365 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301366 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301367 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301369 "action": action,
1370 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001371 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301372 }
1373
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 OnuId: int32(onuID),
1376 UniId: int32(uniID),
1377 FlowId: uplinkFlowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001378 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 AllocId: int32(allocID),
1380 NetworkIntfId: int32(networkIntfID),
1381 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 Classifier: classifierProto,
1383 Action: actionProto,
1384 Priority: int32(logicalFlow.Priority),
1385 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001386 PortNo: portNo,
1387 TechProfileId: tpID,
1388 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001389 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301390 return olterrors.NewErrFlowOp("add", uplinkFlowID, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001392 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301393 log.Fields{
1394 "device-id": f.deviceHandler.device.Id,
1395 "onu-id": onuID,
1396 "intf-id": intfID,
1397 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001398 flowCategory := "EAPOL"
1399 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &upstreamFlow, flowStoreCookie, flowCategory, uplinkFlowID, logicalFlow.Id)
1400 if err := f.updateFlowInfoToKVStore(ctx, upstreamFlow.AccessIntfId,
1401 upstreamFlow.OnuId,
1402 upstreamFlow.UniId,
1403 upstreamFlow.FlowId,
1404 /* lowCategory, */
1405 flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301406 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1407 log.Fields{
1408 "flow": upstreamFlow,
1409 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001411 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301412}
1413
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001415 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001416
1417 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1418 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1419 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001420 if vlanID != ReservedVlan {
1421 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001422 classifier.OVid = vid
1423 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301424 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001425 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1426 vid := uint32(metadata)
1427 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001428 classifier.IVid = vid
1429 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301430 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301431 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001432 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301433 classifier.OPbits = vlanPcp
1434 } else {
1435 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001437 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1438 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1439 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1440 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001441 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001442 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1443 classifier.PktTagType = pktTagType
1444
1445 switch pktTagType {
1446 case SingleTag:
1447 case DoubleTag:
1448 case Untagged:
1449 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001450 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301451 }
1452 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001453 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301454}
1455
Gamze Abaka724d0852020-03-18 12:10:24 +00001456func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 var actionCmd openoltpb2.ActionCmd
1458 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001462 if _, ok := actionInfo[VlanPcp]; ok {
1463 action.Cmd.RemarkInnerPbits = true
1464 action.IPbits = actionInfo[VlanPcp].(uint32)
1465 if _, ok := actionInfo[VlanVid]; ok {
1466 action.Cmd.TranslateInnerTag = true
1467 action.IVid = actionInfo[VlanVid].(uint32)
1468 }
1469 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001470 } else if _, ok := actionInfo[PushVlan]; ok {
1471 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301472 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001473 if _, ok := actionInfo[VlanPcp]; ok {
1474 action.OPbits = actionInfo[VlanPcp].(uint32)
1475 action.Cmd.RemarkOuterPbits = true
1476 if _, ok := classifierInfo[VlanVid]; ok {
1477 action.IVid = classifierInfo[VlanVid].(uint32)
1478 action.Cmd.TranslateInnerTag = true
1479 }
1480 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001481 } else if _, ok := actionInfo[TrapToHost]; ok {
1482 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001484 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301485 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001486 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301487}
1488
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001489// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001490func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1491 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301492}
1493
Gamze Abakafee36392019-10-03 11:17:24 +00001494// DeleteTechProfileInstances removes the tech profile instances from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301495func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, sn string) error {
1496 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001497 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1498
Gamze Abakafee36392019-10-03 11:17:24 +00001499 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301500 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001501 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301502 // return err
1503 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001504 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001505 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001506 }
1507 return nil
1508}
1509
1510// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301511func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001512 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001513 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001514 }
npujarec5762e2020-01-01 14:08:48 +05301515 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301516 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1517 log.Fields{
1518 "tp-id": tpID,
1519 "uni-port-name": uniPortName,
1520 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001521 }
1522 return nil
1523}
1524
Neha Sharma96b7bf22020-06-15 10:37:32 +00001525func getFlowStoreCookie(ctx context.Context, classifier map[string]interface{}, gemPortID uint32) uint64 {
manikkaraj kbf256be2019-03-25 00:13:48 +05301526 if len(classifier) == 0 { // should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00001527 logger.Error(ctx, "invalid-classfier-object")
manikkaraj kbf256be2019-03-25 00:13:48 +05301528 return 0
1529 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001530 logger.Debugw(ctx, "generating-flow-store-cookie",
Shrey Baid26912972020-04-16 21:02:31 +05301531 log.Fields{
1532 "classifier": classifier,
1533 "gemport-id": gemPortID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301534 var jsonData []byte
1535 var flowString string
1536 var err error
1537 // TODO: Do we need to marshall ??
1538 if jsonData, err = json.Marshal(classifier); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001539 logger.Error(ctx, "failed-to-encode-classifier")
manikkaraj kbf256be2019-03-25 00:13:48 +05301540 return 0
1541 }
1542 flowString = string(jsonData)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001543 if gemPortID != 0 {
1544 flowString = fmt.Sprintf("%s%s", string(jsonData), string(gemPortID))
manikkaraj kbf256be2019-03-25 00:13:48 +05301545 }
1546 h := md5.New()
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001547 _, _ = h.Write([]byte(flowString))
manikkaraj kbf256be2019-03-25 00:13:48 +05301548 hash := big.NewInt(0)
1549 hash.SetBytes(h.Sum(nil))
Girish Gowdra3d633032019-12-10 16:37:05 +05301550 generatedHash := hash.Uint64()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001551 logger.Debugw(ctx, "hash-generated", log.Fields{"hash": generatedHash})
Girish Gowdra3d633032019-12-10 16:37:05 +05301552 return generatedHash
manikkaraj kbf256be2019-03-25 00:13:48 +05301553}
1554
npujarec5762e2020-01-01 14:08:48 +05301555func (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 +05301556 var flows = []rsrcMgr.FlowInfo{{Flow: flow, FlowCategory: flowCategory, FlowStoreCookie: flowStoreCookie, LogicalFlowID: logicalFlowID}}
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001557 var intfID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001558 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1559 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1560 */
1561 if flow.AccessIntfId != -1 {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001562 intfID = uint32(flow.AccessIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001563 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001564 intfID = uint32(flow.NetworkIntfId)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04001565 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001566 // Get existing flows matching flowid for given subscriber from KV store
npujarec5762e2020-01-01 14:08:48 +05301567 existingFlows := f.resourceMgr.GetFlowIDInfo(ctx, intfID, flow.OnuId, flow.UniId, flow.FlowId)
manikkaraj k17652a72019-05-06 09:06:36 -04001568 if existingFlows != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569 logger.Debugw(ctx, "flow-exists-for-given-flowID--appending-it-to-current-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301570 log.Fields{
1571 "flow-id": flow.FlowId,
1572 "device-id": f.deviceHandler.device.Id,
1573 "intf-id": intfID,
1574 "onu-id": flow.OnuId})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001575 //for _, f := range *existingFlows {
1576 // flows = append(flows, f)
1577 //}
1578 flows = append(flows, *existingFlows...)
manikkaraj k17652a72019-05-06 09:06:36 -04001579 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001580 logger.Debugw(ctx, "updated-flows-for-given-flowID-and-onuid",
Shrey Baid26912972020-04-16 21:02:31 +05301581 log.Fields{
1582 "updatedflow": flows,
1583 "flow-id": flow.FlowId,
1584 "onu-id": flow.OnuId,
1585 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +05301586 return &flows
1587}
1588
npujarec5762e2020-01-01 14:08:48 +05301589func (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 +00001590 logger.Debugw(ctx, "storing-flow(s)-into-kv-store", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301591 "flow-id": flowID,
1592 "device-id": f.deviceHandler.device.Id,
1593 "intf-id": intfID,
1594 "onu-id": onuID})
npujarec5762e2020-01-01 14:08:48 +05301595 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, intfID, onuID, uniID, flowID, flows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001596 logger.Warnw(ctx, "error-while-storing-flow-into-kv-store", 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 k17652a72019-05-06 09:06:36 -04001601 return err
1602 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Infow(ctx, "stored-flow(s)-into-kv-store-successfully!", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301604 "device-id": f.deviceHandler.device.Id,
1605 "onu-id": onuID,
1606 "intf-id": intfID,
1607 "flow-id": flowID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301608 return nil
1609}
1610
David K. Bainbridge794735f2020-02-11 21:01:37 -08001611func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001612
1613 var intfID uint32
1614 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1615 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1616 */
1617 if deviceFlow.AccessIntfId != -1 {
1618 intfID = uint32(deviceFlow.AccessIntfId)
1619 } else {
Manikkaraj kb1d51442019-07-23 10:41:02 -04001620 // REVIST : Why ponport is given as network port?
Daniele Rossi22db98e2019-07-11 11:50:00 +00001621 intfID = uint32(deviceFlow.NetworkIntfId)
1622 }
1623
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301625 "flow": *deviceFlow,
1626 "device-id": f.deviceHandler.device.Id,
1627 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001628 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 st, _ := status.FromError(err)
1631 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001632 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001633 "err": err,
1634 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301635 "device-id": f.deviceHandler.device.Id,
1636 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001637 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301638 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001639
1640 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301642 log.Fields{"err": err,
1643 "device-flow": deviceFlow,
1644 "device-id": f.deviceHandler.device.Id,
1645 "intf-id": intfID})
npujarec5762e2020-01-01 14:08:48 +05301646 f.resourceMgr.FreeFlowID(ctx, intfID, deviceFlow.OnuId, deviceFlow.UniId, deviceFlow.FlowId)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001648 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301649 if deviceFlow.GemportId != -1 {
1650 // No need to register the flow if it is a trap on nni flow.
Kent Hagermane6ff1012020-07-14 15:07:53 -04001651 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1652 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1653 return err
1654 }
Abhilash Laxmeshwar6d1acb92020-01-17 15:43:03 +05301655 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001656 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301657 log.Fields{
1658 "flow": *deviceFlow,
1659 "device-id": f.deviceHandler.device.Id,
1660 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001662}
1663
Neha Sharma96b7bf22020-06-15 10:37:32 +00001664func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1665 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301666 log.Fields{
1667 "flow": *deviceFlow,
1668 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001669 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001670 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001671 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001672 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301673 log.Fields{
1674 "err": err,
1675 "deviceFlow": deviceFlow,
1676 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001677 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001679 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001680 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001681
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001684 "of-flow-id": ofFlowID,
1685 "flow": *deviceFlow,
1686 "device-id": f.deviceHandler.device.Id,
1687 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301689}
1690
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001692
1693 classifierInfo := make(map[string]interface{})
1694 actionInfo := make(map[string]interface{})
1695
1696 classifierInfo[EthType] = uint32(LldpEthType)
1697 classifierInfo[PacketTagType] = Untagged
1698 actionInfo[TrapToHost] = true
1699
1700 // LLDP flow is installed to trap LLDP packets on the NNI port.
1701 // We manage flow_id resource pool on per PON port basis.
1702 // Since this situation is tricky, as a hack, we pass the NNI port
1703 // index (network_intf_id) as PON port Index for the flow_id resource
1704 // pool. Also, there is no ONU Id available for trapping LLDP packets
1705 // on NNI port, use onu_id as -1 (invalid)
1706 // ****************** CAVEAT *******************
1707 // This logic works if the NNI Port Id falls within the same valid
1708 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1709 // we need to have a re-look at this.
1710 // *********************************************
1711
1712 var onuID = -1
1713 var uniID = -1
1714 var gemPortID = -1
1715
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301718 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001719 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 var flowStoreCookie = getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05301721 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001723 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001724 }
npujarec5762e2020-01-01 14:08:48 +05301725 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0)
Humera Kouser94d7a842019-08-25 19:04:32 -04001726
1727 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301728 return olterrors.NewErrNotFound("flow-id",
1729 log.Fields{
1730 "interface-id": networkInterfaceID,
1731 "onu-id": onuID,
1732 "uni-id": uniID,
1733 "gem-port-id": gemPortID,
1734 "cookie": flowStoreCookie,
1735 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001736 err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001737 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001738 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1739 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301740 return olterrors.NewErrInvalidValue(
1741 log.Fields{
1742 "classifier": classifierInfo,
1743 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301746 log.Fields{
1747 "classifier": *classifierProto,
1748 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001749 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001750 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301751 return olterrors.NewErrInvalidValue(
1752 log.Fields{
1753 "action": actionInfo,
1754 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001755 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301757 log.Fields{
1758 "action": *actionProto,
1759 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001760
1761 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1762 OnuId: int32(onuID), // OnuId not required
1763 UniId: int32(uniID), // UniId not used
1764 FlowId: flowID,
1765 FlowType: Downstream,
1766 NetworkIntfId: int32(networkInterfaceID),
1767 GemportId: int32(gemPortID),
1768 Classifier: classifierProto,
1769 Action: actionProto,
1770 Priority: int32(flow.Priority),
1771 Cookie: flow.Cookie,
1772 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001773 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301774 return olterrors.NewErrFlowOp("add", flowID,
1775 log.Fields{
1776 "flow": downstreamflow,
1777 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "device-id": f.deviceHandler.device.Id,
1782 "onu-id": onuID,
1783 "flow-id": flowID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001784 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, flow.Id)
1785 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
1786 int32(onuID),
1787 int32(uniID),
1788 flowID, flowsToKVStore); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301789 return olterrors.NewErrPersistence("update", "flow", flowID,
1790 log.Fields{
1791 "flow": downstreamflow,
1792 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001793 }
1794 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301795}
1796
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001797func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1798 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001799}
1800
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001801//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001803 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1804 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1805 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301807 log.Fields{
1808 "intf-id": intfID,
1809 "onu-id": onuID,
1810 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001812 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301813 return nil, olterrors.NewErrNotFound("onu-child-device",
1814 log.Fields{
1815 "onu-id": onuID,
1816 "intf-id": intfID,
1817 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001818 }
1819 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1820 //better to ad the device to cache here.
1821 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1822 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001823 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301824 log.Fields{
1825 "intf-id": intfID,
1826 "onu-id": onuID,
1827 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 }
1829
1830 return onuDev.(*OnuDevice), nil
1831}
1832
1833//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001834func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1835 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
1837 "pon-port": intfID,
1838 "onu-id": onuID,
1839 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001840 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001842 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301843 return nil, olterrors.NewErrNotFound("onu",
1844 log.Fields{
1845 "interface-id": parentPortNo,
1846 "onu-id": onuID,
1847 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001848 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301849 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
1852 "device-id": f.deviceHandler.device.Id,
1853 "child_device_id": onuDevice.Id,
1854 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301855 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301856}
1857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1859 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
1863 "intf-id": intfID,
1864 "onu-id": onuID,
1865 "uni-id": uniID,
1866 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001867 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301868 }
1869
1870 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301872 log.Fields{
1873 "msg": *delGemPortMsg,
1874 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001875 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301876 delGemPortMsg,
1877 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301878 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001879 onuDev.deviceType,
1880 onuDev.deviceID,
1881 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301882 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1883 log.Fields{
1884 "from-adapter": f.deviceHandler.device.Type,
1885 "to-adapter": onuDev.deviceType,
1886 "onu-id": onuDev.deviceID,
1887 "proxyDeviceID": onuDev.proxyDeviceID,
1888 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301889 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001890 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301891 log.Fields{
1892 "msg": delGemPortMsg,
1893 "from-adapter": f.deviceHandler.device.Type,
1894 "to-adapter": onuDev.deviceType,
1895 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301896 return nil
1897}
1898
Neha Sharma96b7bf22020-06-15 10:37:32 +00001899func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1900 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001902 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301903 log.Fields{
1904 "intf-id": intfID,
1905 "onu-id": onuID,
1906 "uni-id": uniID,
1907 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001908 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301909 }
1910
1911 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301913 log.Fields{
1914 "msg": *delTcontMsg,
1915 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001916 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301917 delTcontMsg,
1918 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301919 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001920 onuDev.deviceType,
1921 onuDev.deviceID,
1922 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301923 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1924 log.Fields{
1925 "from-adapter": f.deviceHandler.device.Type,
1926 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1927 "proxyDeviceID": onuDev.proxyDeviceID,
1928 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301929 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001930 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301931 log.Fields{
1932 "msg": delTcontMsg,
1933 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301934 return nil
1935}
1936
Girish Gowdrac3037402020-01-22 20:29:53 +05301937// Once the gemport is released for a given onu, it also has to be cleared from local cache
1938// which was used for deriving the gemport->logicalPortNo during packet-in.
1939// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1940// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001941func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001942
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001943 f.onuGemInfoLock.Lock()
1944 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001945
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301947 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001948 "gem-port-id": gemPortID,
1949 "intf-id": intfID,
1950 "onu-id": onuID,
1951 "device-id": f.deviceHandler.device.Id,
1952 "onu-gem": f.onuGemInfo[intfID]})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001953
Girish Gowdrac3037402020-01-22 20:29:53 +05301954 onugem := f.onuGemInfo[intfID]
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001955deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001956 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301957 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001958 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301959 // If the gemport is found, delete it from local cache.
1960 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001961 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1962 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001963 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301964 log.Fields{
1965 "intf-id": intfID,
1966 "onu-id": onuID,
1967 "deletedgemport-id": gemPortID,
1968 "gemports": onu.GemPorts,
1969 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001970 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301971 }
1972 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001973 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301974 }
1975 }
1976}
1977
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301978//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001979// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301980func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301981 gemPortID int32, flowID uint32, flowDirection string,
1982 portNum uint32, updatedFlows []rsrcMgr.FlowInfo) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001983
Neha Sharma96b7bf22020-06-15 10:37:32 +00001984 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001985 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301986 return olterrors.NewErrNotFound("tp-id",
1987 log.Fields{
1988 "flow": flow,
1989 "intf": Intf,
1990 "onu-id": onuID,
1991 "uni-id": uniID,
1992 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001993 }
Gamze Abakafee36392019-10-03 11:17:24 +00001994
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001995 if len(updatedFlows) >= 0 {
1996 // There are still flows referencing the same flow_id.
1997 // So the flow should not be freed yet.
1998 // For ex: Case of HSIA where same flow is shared
1999 // between DS and US.
Girish Kumarf26e4882020-03-05 06:49:10 +00002000 if err := f.updateFlowInfoToKVStore(ctx, int32(Intf), int32(onuID), int32(uniID), flowID, &updatedFlows); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002001 _ = olterrors.NewErrPersistence("update", "flow", flowID,
Shrey Baid26912972020-04-16 21:02:31 +05302002 log.Fields{
2003 "flow": updatedFlows,
2004 "device-id": f.deviceHandler.device.Id}, err).Log()
Girish Kumarf26e4882020-03-05 06:49:10 +00002005 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002006 if len(updatedFlows) == 0 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002007 logger.Debugw(ctx, "releasing-flow-id-to-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302008 log.Fields{
2009 "Intf": Intf,
2010 "onu-id": onuID,
2011 "uni-id": uniID,
2012 "flow-id": flowID,
2013 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302014 f.resourceMgr.FreeFlowID(ctx, Intf, int32(onuID), int32(uniID), flowID)
Manikkaraj kb1d51442019-07-23 10:41:02 -04002015
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002016 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002017 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
2018 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
Shrey Baid26912972020-04-16 21:02:31 +05302019 log.Fields{
2020 "TP-PATH": tpPath,
2021 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +05302022 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Kumarf26e4882020-03-05 06:49:10 +00002023 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
Shrey Baid26912972020-04-16 21:02:31 +05302024 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
2025 log.Fields{
2026 "tp-id": tpID,
2027 "path": tpPath}, err)
Gamze Abakafee36392019-10-03 11:17:24 +00002028 }
2029
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302030 gemPK := gemPortKey{Intf, uint32(gemPortID)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002031 used, err := f.isGemPortUsedByAnotherFlow(ctx, gemPK)
2032 if err != nil {
2033 return err
2034 }
2035 if used {
2036 if f.perGemPortLock.TryLock(gemPK) {
2037 flowIDs := f.flowsUsedByGemPort[gemPK]
2038 for i, flowIDinMap := range flowIDs {
2039 if flowIDinMap == flowID {
2040 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
2041 // everytime flowsUsedByGemPort cache is updated the same should be updated
2042 // in kv store by calling UpdateFlowIDsForGem
2043 f.flowsUsedByGemPort[gemPK] = flowIDs
2044 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
2045 return err
2046 }
2047 break
Kent Hagermane6ff1012020-07-14 15:07:53 -04002048 }
Gamze Abakafee36392019-10-03 11:17:24 +00002049 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002050 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2051 log.Fields{
2052 "gemport-id": gemPortID,
2053 "usedByFlows": flowIDs,
2054 "device-id": f.deviceHandler.device.Id})
2055 f.perGemPortLock.Unlock(gemPK)
2056 return nil
Gamze Abakafee36392019-10-03 11:17:24 +00002057 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002058
2059 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
Shrey Baid26912972020-04-16 21:02:31 +05302060 log.Fields{
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002061 "gemport-id": gemPortID,
2062 "device-id": f.deviceHandler.device.Id,
2063 "key": gemPK,
2064 })
2065 return olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
2066 "gemport-id": gemPortID,
2067 "device-id": f.deviceHandler.device.Id,
2068 "key": gemPK,
2069 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00002070 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002071 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
npujarec5762e2020-01-01 14:08:48 +05302072 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002073 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
2074 // 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 +05302075 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002077 f.onuIdsLock.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05302078 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
2079 // by calling DeleteFlowIDsForGem
Matteo Scandolo738c52a2020-08-03 11:14:22 -07002080 if f.perGemPortLock.TryLock(gemPK) {
2081 delete(f.flowsUsedByGemPort, gemPK)
2082 f.perGemPortLock.Unlock(gemPK)
2083 } else {
2084 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
2085 log.Fields{
2086 "device-id": f.deviceHandler.device.Id,
2087 "key": gemPK,
2088 })
2089 }
npujarec5762e2020-01-01 14:08:48 +05302090 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
2091 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
Gamze Abakafee36392019-10-03 11:17:24 +00002092 f.onuIdsLock.Unlock()
Girish Gowdra6b130582019-11-20 16:45:20 +05302093 // Delete the gem port on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002094 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
2095 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302096 log.Fields{
2097 "err": err,
2098 "intf": Intf,
2099 "onu-id": onuID,
2100 "uni-id": uniID,
2101 "device-id": f.deviceHandler.device.Id,
2102 "gemport-id": gemPortID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302103 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002104 switch techprofileInst := techprofileInst.(type) {
2105 case *tp.TechProfile:
2106 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
2107 if !ok {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002108 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2109 logger.Warn(ctx, err)
2110 }
2111 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2112 logger.Warn(ctx, err)
2113 }
2114 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2115 logger.Warn(ctx, err)
2116 }
2117 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
2118 logger.Warn(ctx, err)
2119 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002120 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2121 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002122 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.UsScheduler.AllocID), tpPath); err != nil {
2123 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002124 log.Fields{
2125 "intf": Intf,
2126 "onu-id": onuID,
2127 "uni-id": uniID,
2128 "device-id": f.deviceHandler.device.Id,
2129 "alloc-id": techprofileInst.UsScheduler.AllocID})
2130 }
2131 }
2132 case *tp.EponProfile:
Kent Hagermane6ff1012020-07-14 15:07:53 -04002133 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2134 logger.Warn(ctx, err)
2135 }
2136 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2137 logger.Warn(ctx, err)
2138 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002139 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdra6b130582019-11-20 16:45:20 +05302140 // Delete the TCONT on the ONU.
Neha Sharma96b7bf22020-06-15 10:37:32 +00002141 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(techprofileInst.AllocID), tpPath); err != nil {
2142 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302143 log.Fields{
2144 "intf": Intf,
2145 "onu-id": onuID,
2146 "uni-id": uniID,
2147 "device-id": f.deviceHandler.device.Id,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002148 "alloc-id": techprofileInst.AllocID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302149 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002150 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002151 logger.Errorw(ctx, "error-unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002152 log.Fields{
2153 "techprofileInst": techprofileInst})
Gamze Abakafee36392019-10-03 11:17:24 +00002154 }
2155 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002156 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302157 return nil
2158}
2159
David K. Bainbridge794735f2020-02-11 21:01:37 -08002160// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302161func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) {
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302162
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302164 log.Fields{
2165 "flowDirection": flowDirection,
2166 "flow": *flow,
2167 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002168
2169 if flowDirection == Multicast {
npujarec5762e2020-01-01 14:08:48 +05302170 f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002171 return
2172 }
2173
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302174 classifierInfo := make(map[string]interface{})
2175
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302177 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002178 logger.Error(ctx, err)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302179 return
2180 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302181
David K. Bainbridge794735f2020-02-11 21:01:37 -08002182 onuID := int32(onu)
2183 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302184
2185 for _, field := range flows.GetOfbFields(flow) {
2186 if field.Type == flows.IP_PROTO {
2187 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002188 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302189 }
2190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002191 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302192 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002193 "flow-id": flow.Id,
2194 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302195 "onu-id": onuID,
2196 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302197
2198 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2199 onuID = -1
2200 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002201 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2202 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002203 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002204 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002205 log.Fields{
2206 "port-number": inPort,
2207 "error": err})
2208 return
2209 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302210 }
npujarec5762e2020-01-01 14:08:48 +05302211 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, Intf, onuID, uniID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002212 for _, flowID := range flowIds {
npujarec5762e2020-01-01 14:08:48 +05302213 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flowID)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302214 if flowInfo == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002215 logger.Debugw(ctx, "no-flowinfo-found-in-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302216 log.Fields{
2217 "intf": Intf,
2218 "onu-id": onuID,
2219 "uni-id": uniID,
2220 "flow-id": flowID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302221 return
2222 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302223
Kent Hagermane6ff1012020-07-14 15:07:53 -04002224 updatedFlows := *flowInfo
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302225 for i, storedFlow := range updatedFlows {
2226 if flow.Id == storedFlow.LogicalFlowID {
2227 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002228 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": storedFlow})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002229 // DKB
Neha Sharma96b7bf22020-06-15 10:37:32 +00002230 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2231 logger.Errorw(ctx, "failed-to-remove-flow", log.Fields{"error": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002232 return
2233 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Info(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002235 "flow-id": flow.Id,
2236 "stored-flow": storedFlow,
2237 "device-id": f.deviceHandler.device.Id,
2238 "stored-flow-id": flowID,
2239 "onu-id": onuID,
2240 "intf": Intf,
2241 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08002242 //Remove the Flow from FlowInfo
2243 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
2244 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, storedFlow.Flow.GemportId,
2245 flowID, flowDirection, portNum, updatedFlows); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002246 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002247 "flow-id": flow.Id,
2248 "stored-flow": storedFlow,
2249 "device-id": f.deviceHandler.device.Id,
2250 "stored-flow-id": flowID,
2251 "onu-id": onuID,
2252 "intf": Intf,
2253 })
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302254 return
2255 }
2256 }
2257 }
2258 }
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002259}
2260
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002261//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002262func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302264 var direction string
2265 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002266
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302267 for _, action := range flows.GetActions(flow) {
2268 if action.Type == flows.OUTPUT {
2269 if out := action.GetOutput(); out != nil {
2270 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002271 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302272 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002273 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002274 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002275 }
2276 }
2277 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002278
Girish Gowdra9602eb42020-09-09 15:50:39 -07002279 f.incrementActiveFlowRemoveCount(ctx, flow)
2280 defer f.decrementActiveFlowRemoveCount(ctx, flow)
2281
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 if flows.HasGroup(flow) {
2283 direction = Multicast
Girish Gowdracefae192020-03-19 18:14:10 -07002284 f.clearFlowFromResourceManager(ctx, flow, direction)
2285 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002286 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302287 direction = Upstream
2288 } else {
2289 direction = Downstream
2290 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302291
Neha Sharma96b7bf22020-06-15 10:37:32 +00002292 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002293 if err != nil {
2294 return err
2295 }
2296
2297 userKey := tpLockKey{intfID, onuID, uniID}
2298
2299 // Serialize flow removes on a per subscriber basis
2300 if f.perUserFlowHandleLock.TryLock(userKey) {
2301 f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
2302 f.perUserFlowHandleLock.Unlock(userKey)
2303 } else {
2304 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002305 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002306 return errors.New("failed-to-acquire-per-user-lock")
2307 }
2308
2309 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002310}
2311
Esin Karamanae41e2b2019-12-17 18:13:13 +00002312//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2313func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2314 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2315 if ethType, ok := classifierInfo[EthType]; ok {
2316 if ethType.(uint32) == IPv4EthType {
2317 if ipProto, ok := classifierInfo[IPProto]; ok {
2318 if ipProto.(uint32) == IgmpProto {
2319 return true
2320 }
2321 }
2322 }
2323 }
2324 }
2325 return false
2326}
2327
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002328// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302329// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002330func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002331 classifierInfo := make(map[string]interface{})
2332 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002333 var UsMeterID uint32
2334 var DsMeterID uint32
2335
Neha Sharma96b7bf22020-06-15 10:37:32 +00002336 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302337 log.Fields{
2338 "flow": flow,
2339 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002341
Neha Sharma96b7bf22020-06-15 10:37:32 +00002342 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002343 if err != nil {
2344 // Error logging is already done in the called function
2345 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002346 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302347 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002348
Esin Karamanccb714b2019-11-29 15:02:06 +00002349 if flows.HasGroup(flow) {
2350 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002351 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002352 }
2353
manikkaraj k17652a72019-05-06 09:06:36 -04002354 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002355 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002356 if err != nil {
2357 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002358 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002359 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002360
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302362 log.Fields{
2363 "classifierinfo_inport": classifierInfo[InPort],
2364 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002365 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002366
Humera Kouser94d7a842019-08-25 19:04:32 -04002367 if ethType, ok := classifierInfo[EthType]; ok {
2368 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002369 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002370 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002371 }
2372 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373 if ipProto, ok := classifierInfo[IPProto]; ok {
2374 if ipProto.(uint32) == IPProtoDhcp {
2375 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302376 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002377 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002378 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002379 }
2380 }
2381 }
2382 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002383 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002385 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002386 }
A R Karthick1f85b802019-10-11 05:06:05 +00002387
Girish Gowdra9602eb42020-09-09 15:50:39 -07002388 // If we are here it is not a trap-from-nni flow, i.e., it is subscriber specific flow.
2389 // Wait for any FlowRemoves for that specific subscriber to finish first
2390 // The goal here is to serialize FlowRemove and FlowAdd. FlowRemove take priority
2391 f.waitForFlowRemoveToFinish(ctx, flow)
2392
npujarec5762e2020-01-01 14:08:48 +05302393 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002394
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302397 return olterrors.NewErrNotFound("tpid-for-flow",
2398 log.Fields{
2399 "flow": flow,
2400 "intf-id": IntfID,
2401 "onu-id": onuID,
2402 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002403 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002404 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302405 log.Fields{
2406 "tp-id": TpID,
2407 "intf-id": intfID,
2408 "onu-id": onuID,
2409 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002410 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002411 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002413 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002414 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002416
2417 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002418 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, uint32(TpID), UsMeterID, DsMeterID, flowMetadata)
2419}
Girish Gowdra3d633032019-12-10 16:37:05 +05302420
Girish Gowdra9602eb42020-09-09 15:50:39 -07002421//WaitForFlowRemoveToFinishForSubscriber blocks until flow removes are complete for a given subscriber
2422func (f *OpenOltFlowMgr) WaitForFlowRemoveToFinishForSubscriber(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) {
2423 var flowRemoveData pendingFlowRemoveData
2424 var ok bool
2425
2426 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2427 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2428
2429 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
2430 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2431 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2432 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2433 return
Girish Gowdra3d633032019-12-10 16:37:05 +05302434 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002435 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2436
2437 // Wait for all flow removes to finish first
2438 <-flowRemoveData.allFlowsRemoved
2439
2440 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002441}
2442
Esin Karamanccb714b2019-11-29 15:02:06 +00002443// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002444func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002445 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302447 "classifier-info": classifierInfo,
2448 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002449
Esin Karaman65409d82020-03-18 10:58:18 +00002450 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002451 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002452 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002453 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002454 //this variable acts like a switch. When it is set, multicast flows are classified by eth_dst.
2455 //otherwise, classification is based on ipv4_dst by default.
2456 //the variable can be configurable in the future; it can be read from a configuration path in the kv store.
2457 mcastFlowClassificationByEthDst := false
2458
2459 if mcastFlowClassificationByEthDst {
2460 //replace ipDst with ethDst
2461 if ipv4Dst, ok := classifierInfo[Ipv4Dst]; ok &&
2462 flows.IsMulticastIp(ipv4Dst.(uint32)) {
2463 // replace ipv4_dst classifier with eth_dst
2464 multicastMac := flows.ConvertToMulticastMacBytes(ipv4Dst.(uint32))
2465 delete(classifierInfo, Ipv4Dst)
2466 classifierInfo[EthDst] = multicastMac
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 logger.Debugw(ctx, "multicast-ip-to-mac-conversion-success",
Shrey Baid26912972020-04-16 21:02:31 +05302468 log.Fields{
2469 "ip:": ipv4Dst.(uint32),
2470 "mac:": multicastMac})
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002471 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002472 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002473 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002474
David K. Bainbridge794735f2020-02-11 21:01:37 -08002475 onuID := NoneOnuID
2476 uniID := NoneUniID
2477 gemPortID := NoneGemPortID
Esin Karamanccb714b2019-11-29 15:02:06 +00002478
Neha Sharma96b7bf22020-06-15 10:37:32 +00002479 flowStoreCookie := getFlowStoreCookie(ctx, classifierInfo, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302480 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002482 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002483 }
npujarec5762e2020-01-01 14:08:48 +05302484 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanccb714b2019-11-29 15:02:06 +00002485 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302486 return olterrors.NewErrNotFound("multicast-flow-id",
2487 log.Fields{
2488 "interface-id": networkInterfaceID,
2489 "onu-id": onuID,
2490 "uni-id": uniID,
2491 "gem-port-id": gemPortID,
2492 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002493 err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002494 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002495 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2496 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002497 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002498 }
2499 groupID := actionInfo[GroupID].(uint32)
2500 multicastFlow := openoltpb2.Flow{
2501 FlowId: flowID,
2502 FlowType: Multicast,
2503 NetworkIntfId: int32(networkInterfaceID),
2504 GroupId: groupID,
2505 Classifier: classifierProto,
2506 Priority: int32(flow.Priority),
2507 Cookie: flow.Cookie}
2508
Kent Hagermane6ff1012020-07-14 15:07:53 -04002509 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002510 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002511 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002512 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002513 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002514 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002515 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002516 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002517 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002518 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002519 //cached group can be removed now
2520 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2521 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2522 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002523 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002524
2525 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &multicastFlow, flowStoreCookie, MulticastFlow, flowID, flow.Id)
2526 if err = f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
2527 int32(onuID),
2528 int32(uniID),
2529 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002530 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002531 }
2532 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002533}
2534
Esin Karaman65409d82020-03-18 10:58:18 +00002535//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2536func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2537 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002538 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002539 if err != nil {
2540 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2541 }
2542 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002543 }
Esin Karaman65409d82020-03-18 10:58:18 +00002544 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302545 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002546 if e == nil && len(nniPorts) > 0 {
2547 return nniPorts[0], nil
2548 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302549 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002550}
2551
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002552//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002553func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002554
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302556 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002557 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302558 log.Fields{
2559 "intf-id": intfID,
2560 "onu-id": onuID,
2561 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002562 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302563 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002564 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002565
Neha Sharma96b7bf22020-06-15 10:37:32 +00002566 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002567 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002569 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002570 tpDownloadMsg,
2571 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302572 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002573 onuDev.deviceType,
2574 onuDev.deviceID,
2575 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002576 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302577 return olterrors.NewErrCommunication("send-techprofile-download-request",
2578 log.Fields{
2579 "from-adapter": f.deviceHandler.device.Type,
2580 "to-adapter": onuDev.deviceType,
2581 "onu-id": onuDev.deviceID,
2582 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302585 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302586}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002587
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302588//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002589func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302590
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002591 f.onuGemInfoLock.Lock()
2592 defer f.onuGemInfoLock.Unlock()
Girish Gowdra9602eb42020-09-09 15:50:39 -07002593 onugem := f.onuGemInfo[intfID]
2594 // If the ONU already exists in onuGemInfo list, nothing to do
2595 for _, onu := range onugem {
2596 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2597 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2598 log.Fields{"onuID": onuID,
2599 "serialNum": serialNum})
2600 return nil
2601 }
2602 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002603
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302604 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
2605 f.onuGemInfo[intfID] = append(f.onuGemInfo[intfID], onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002606 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002607 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302608 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002609 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302610 log.Fields{
2611 "intf-id": intfID,
2612 "onu-id": onuID,
2613 "serial-num": serialNum,
2614 "onu": onu,
2615 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002616 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002617}
2618
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302619//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302620func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002621
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002622 f.onuGemInfoLock.Lock()
2623 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002624
Neha Sharma96b7bf22020-06-15 10:37:32 +00002625 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302626 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002627 "gem-port-id": gemPort,
2628 "intf-id": intfID,
2629 "onu-id": onuID,
2630 "device-id": f.deviceHandler.device.Id,
2631 "onu-gem": f.onuGemInfo[intfID]})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 onugem := f.onuGemInfo[intfID]
2633 // update the gem to the local cache as well as to kv strore
2634 for idx, onu := range onugem {
2635 if onu.OnuID == onuID {
2636 // check if gem already exists , else update the cache and kvstore
2637 for _, gem := range onu.GemPorts {
2638 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002639 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302640 log.Fields{
2641 "gem": gemPort,
2642 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302643 return
2644 }
2645 }
2646 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
2647 f.onuGemInfo[intfID] = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002648 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302649 }
2650 }
npujarec5762e2020-01-01 14:08:48 +05302651 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302652 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002653 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302654 log.Fields{
2655 "intf-id": intfID,
2656 "onu-id": onuID,
2657 "gemPort": gemPort,
2658 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659 return
2660 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002661 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302662 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002663 "gem-port-id": gemPort,
2664 "intf-id": intfID,
2665 "onu-id": onuID,
2666 "device-id": f.deviceHandler.device.Id,
2667 "onu-gem": f.onuGemInfo[intfID]})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002668}
2669
2670// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002671
2672//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 +00002673func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302674
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002675 f.onuGemInfoLock.RLock()
2676 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302677
Neha Sharma96b7bf22020-06-15 10:37:32 +00002678 logger.Infow(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302679 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002680 "device-id": f.deviceHandler.device.Id,
2681 "onu-geminfo": f.onuGemInfo[intfID],
2682 "intf-id": intfID,
2683 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302684 // get onuid from the onugem info cache
2685 onugem := f.onuGemInfo[intfID]
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002686
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302687 for _, onu := range onugem {
2688 for _, gem := range onu.GemPorts {
2689 if gem == gemPortID {
2690 return onu.OnuID, nil
2691 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002692 }
2693 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002694 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2695 "gem-port-id": gemPortID,
2696 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002697 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002698 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302699 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002700 "interface-id": intfID,
2701 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002702 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002703}
2704
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002705//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302706func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002707 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002708 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002709 var err error
2710
2711 if packetIn.IntfType == "pon" {
2712 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002713 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002714 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715 return logicalPortNum, err
2716 }
2717 if packetIn.PortNo != 0 {
2718 logicalPortNum = packetIn.PortNo
2719 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002720 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002722 }
2723 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman7fb80c22020-07-16 14:23:33 +00002724 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002725 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002726 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002727 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05302729 log.Fields{
2730 "logical-port-num": logicalPortNum,
2731 "intf-type": packetIn.IntfType,
2732 "packet": hex.EncodeToString(packetIn.Pkt),
2733 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002734 return logicalPortNum, nil
2735}
2736
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002737//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002738func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002739 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002740
2741 ctag, priority, err := getCTagFromPacket(ctx, packet)
2742 if err != nil {
2743 return 0, err
2744 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302745
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002746 f.onuGemInfoLock.RLock()
2747 defer f.onuGemInfoLock.RUnlock()
Esin Karaman7fb80c22020-07-16 14:23:33 +00002748 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002749 var ok bool
2750 gemPortID, ok = f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302751 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002752 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302753 log.Fields{
2754 "pktinkey": pktInkey,
2755 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002756
2757 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002758 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302759 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman7fb80c22020-07-16 14:23:33 +00002760 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302761 if err == nil {
2762 if gemPortID != 0 {
2763 f.packetInGemPort[pktInkey] = gemPortID
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302765 log.Fields{
2766 "pktinkey": pktInkey,
2767 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302768 return gemPortID, nil
2769 }
2770 }
Shrey Baid26912972020-04-16 21:02:31 +05302771 return uint32(0), olterrors.NewErrNotFound("gem-port",
2772 log.Fields{
2773 "pktinkey": pktInkey,
2774 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002775
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002776}
2777
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002778// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302779func installFlowOnAllGemports(ctx context.Context,
2780 f1 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002781 portNo uint32, classifier map[string]interface{}, action map[string]interface{},
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002782 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, tpID uint32) error,
npujarec5762e2020-01-01 14:08:48 +05302783 f2 func(ctx context.Context, intfId uint32, onuId uint32, uniId uint32, portNo uint32,
Girish Gowdrafae935c2020-02-17 19:21:44 +05302784 classifier map[string]interface{}, action map[string]interface{},
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302785 logicalFlow *ofp.OfpFlowStats, allocId uint32, gemPortId uint32, vlanId uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002786 tpID uint32) error,
Manikkaraj kb1d51442019-07-23 10:41:02 -04002787 args map[string]uint32,
2788 classifier map[string]interface{}, action map[string]interface{},
2789 logicalFlow *ofp.OfpFlowStats,
2790 gemPorts []uint32,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002791 TpInst interface{},
Manikkaraj kb1d51442019-07-23 10:41:02 -04002792 FlowType string,
Gamze Abaka724d0852020-03-18 12:10:24 +00002793 direction string,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002794 tpID uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +00002795 vlanID ...uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002796 logger.Debugw(ctx, "installing-flow-on-all-gem-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302797 log.Fields{
2798 "FlowType": FlowType,
2799 "gemPorts": gemPorts,
2800 "vlan": vlanID})
Girish Gowdrafae935c2020-02-17 19:21:44 +05302801
Gamze Abaka724d0852020-03-18 12:10:24 +00002802 // The bit mapping for a gemport is expressed in tech-profile as a binary string. For example, 0b00000001
2803 // We need to trim prefix "0b", before further processing
2804 // Once the "0b" prefix is trimmed, we iterate each character in the string to identify which index
2805 // in the string is set to binary bit 1 (expressed as char '1' in the binary string).
2806
2807 // If a particular character in the string is set to '1', identify the index of this character from
2808 // the LSB position which marks the PCP bit consumed by the given gem port.
2809 // This PCP bit now becomes a classifier in the flow.
2810
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002811 switch TpInst := TpInst.(type) {
2812 case *tp.TechProfile:
2813 attributes := TpInst.DownstreamGemPortAttributeList
2814 if direction == Upstream {
2815 attributes = TpInst.UpstreamGemPortAttributeList
Gamze Abaka724d0852020-03-18 12:10:24 +00002816 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002817
2818 for _, gemPortAttribute := range attributes {
2819 if direction == Downstream && strings.ToUpper(gemPortAttribute.IsMulticast) == "TRUE" {
2820 continue
Gamze Abaka724d0852020-03-18 12:10:24 +00002821 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002822 gemPortID := gemPortAttribute.GemportID
2823 if allPbitsMarked(gemPortAttribute.PbitMap) {
2824 classifier[VlanPcp] = uint32(VlanPCPMask)
2825 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002826 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2827 logger.Warn(ctx, err)
2828 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002829 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002830 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2831 logger.Warn(ctx, err)
2832 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002833 }
2834 } else {
2835 for pos, pbitSet := range strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix) {
2836 if pbitSet == BinaryBit1 {
2837 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(gemPortAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2838 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002839 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2840 logger.Warn(ctx, err)
2841 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002842 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002843 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2844 logger.Warn(ctx, err)
2845 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002846 }
2847 }
2848 }
2849 }
2850 }
2851 case *tp.EponProfile:
2852 if direction == Upstream {
2853 attributes := TpInst.UpstreamQueueAttributeList
2854 for _, queueAttribute := range attributes {
2855 gemPortID := queueAttribute.GemportID
2856 if allPbitsMarked(queueAttribute.PbitMap) {
2857 classifier[VlanPcp] = uint32(VlanPCPMask)
Gamze Abaka724d0852020-03-18 12:10:24 +00002858 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002859 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2860 logger.Warn(ctx, err)
2861 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002862 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002863 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2864 logger.Warn(ctx, err)
2865 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002866 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002867 } else {
2868 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
2869 if pbitSet == BinaryBit1 {
2870 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2871 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002872 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2873 logger.Warn(ctx, err)
2874 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002875 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002876 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2877 logger.Warn(ctx, err)
2878 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002879 }
2880 }
2881 }
2882 }
2883 }
2884 } else {
2885 attributes := TpInst.DownstreamQueueAttributeList
2886 for _, queueAttribute := range attributes {
2887 gemPortID := queueAttribute.GemportID
2888 if allPbitsMarked(queueAttribute.PbitMap) {
2889 classifier[VlanPcp] = uint32(VlanPCPMask)
2890 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002891 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2892 logger.Warn(ctx, err)
2893 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002894 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002895 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2896 logger.Warn(ctx, err)
2897 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002898 }
2899 } else {
2900 for pos, pbitSet := range strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix) {
2901 if pbitSet == BinaryBit1 {
2902 classifier[VlanPcp] = uint32(len(strings.TrimPrefix(queueAttribute.PbitMap, BinaryStringPrefix))) - 1 - uint32(pos)
2903 if FlowType == DhcpFlow || FlowType == IgmpFlow || FlowType == HsiaFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002904 if err := f1(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, tpID); err != nil {
2905 logger.Warn(ctx, err)
2906 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002907 } else if FlowType == EapolFlow {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002908 if err := f2(ctx, args["intfId"], args["onuId"], args["uniId"], args["portNo"], classifier, action, logicalFlow, args["allocId"], gemPortID, vlanID[0], tpID); err != nil {
2909 logger.Warn(ctx, err)
2910 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002911 }
2912 }
2913 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05302914 }
2915 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002916 }
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002917 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpInst": TpInst})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002919 }
2920}
2921
Gamze Abaka724d0852020-03-18 12:10:24 +00002922func allPbitsMarked(pbitMap string) bool {
2923 for pos, pBit := range pbitMap {
2924 if pos >= 2 && pBit != BinaryBit1 {
2925 return false
2926 }
2927 }
2928 return true
2929}
2930
David K. Bainbridge794735f2020-02-11 21:01:37 -08002931func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002932 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002933 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002934 classifier[PacketTagType] = DoubleTag
2935 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002936 /* We manage flowId resource pool on per PON port basis.
2937 Since this situation is tricky, as a hack, we pass the NNI port
2938 index (network_intf_id) as PON port Index for the flowId resource
2939 pool. Also, there is no ONU Id available for trapping DHCP packets
2940 on NNI port, use onu_id as -1 (invalid)
2941 ****************** CAVEAT *******************
2942 This logic works if the NNI Port Id falls within the same valid
2943 range of PON Port Ids. If this doesn't work for some OLT Vendor
2944 we need to have a re-look at this.
2945 *********************************************
2946 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002947 onuID := -1
2948 uniID := -1
2949 gemPortID := -1
2950 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002951 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302952 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302953 return olterrors.NewErrNotFound("nni-intreface-id",
2954 log.Fields{
2955 "classifier": classifier,
2956 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002957 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302958 }
2959
Neha Sharma96b7bf22020-06-15 10:37:32 +00002960 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05302961 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002963 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002964 }
Gamze Abaka724d0852020-03-18 12:10:24 +00002965 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002966 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302967 return olterrors.NewErrNotFound("dhcp-trap-nni-flow-id",
2968 log.Fields{
2969 "interface-id": networkInterfaceID,
2970 "onu-id": onuID,
2971 "uni-id": uniID,
2972 "gem-port-id": gemPortID,
2973 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00002974 err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002975 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002976 classifierProto, err := makeOpenOltClassifierField(classifier)
2977 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002978 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002979 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002980 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002981 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002982 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002983 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002984 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002986 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2987 OnuId: int32(onuID), // OnuId not required
2988 UniId: int32(uniID), // UniId not used
2989 FlowId: flowID,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002990 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002991 AllocId: int32(allocID), // AllocId not used
2992 NetworkIntfId: int32(networkInterfaceID),
2993 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002994 Classifier: classifierProto,
2995 Action: actionProto,
2996 Priority: int32(logicalFlow.Priority),
2997 Cookie: logicalFlow.Cookie,
2998 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002999 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003000 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003001 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003002 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003003 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3004 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3005 int32(onuID),
3006 int32(uniID),
3007 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003008 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003009 }
3010 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04003011}
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012
Esin Karamanae41e2b2019-12-17 18:13:13 +00003013//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
3014func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
3015 var packetType string
3016 ovid, ivid := false, false
3017 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
3018 vid := vlanID & VlanvIDMask
3019 if vid != ReservedVlan {
3020 ovid = true
3021 }
3022 }
3023 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
3024 vid := uint32(metadata)
3025 if vid != ReservedVlan {
3026 ivid = true
3027 }
3028 }
3029 if ovid && ivid {
3030 packetType = DoubleTag
3031 } else if !ovid && !ivid {
3032 packetType = Untagged
3033 } else {
3034 packetType = SingleTag
3035 }
3036 return packetType
3037}
3038
3039//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08003040func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003042 action := make(map[string]interface{})
3043 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
3044 action[TrapToHost] = true
3045 /* We manage flowId resource pool on per PON port basis.
3046 Since this situation is tricky, as a hack, we pass the NNI port
3047 index (network_intf_id) as PON port Index for the flowId resource
3048 pool. Also, there is no ONU Id available for trapping packets
3049 on NNI port, use onu_id as -1 (invalid)
3050 ****************** CAVEAT *******************
3051 This logic works if the NNI Port Id falls within the same valid
3052 range of PON Port Ids. If this doesn't work for some OLT Vendor
3053 we need to have a re-look at this.
3054 *********************************************
3055 */
3056 onuID := -1
3057 uniID := -1
3058 gemPortID := -1
3059 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003061 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05303062 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08003063 "classifier": classifier,
3064 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00003065 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003066 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 flowStoreCookie := getFlowStoreCookie(ctx, classifier, uint32(0))
npujarec5762e2020-01-01 14:08:48 +05303068 if present := f.resourceMgr.IsFlowCookieOnKVStore(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), flowStoreCookie); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003070 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003071 }
npujarec5762e2020-01-01 14:08:48 +05303072 flowID, err := f.resourceMgr.GetFlowID(ctx, uint32(networkInterfaceID), int32(onuID), int32(uniID), uint32(gemPortID), flowStoreCookie, "", 0, 0)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05303074 return olterrors.NewErrNotFound("igmp-flow-id",
3075 log.Fields{
3076 "interface-id": networkInterfaceID,
3077 "onu-id": onuID,
3078 "uni-id": uniID,
3079 "gem-port-id": gemPortID,
3080 "cookie": flowStoreCookie},
Girish Kumarf26e4882020-03-05 06:49:10 +00003081 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003082 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08003083 classifierProto, err := makeOpenOltClassifierField(classifier)
3084 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003085 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003086 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003087 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00003088 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003089 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003090 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003091 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003092 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003093 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
3094 OnuId: int32(onuID), // OnuId not required
3095 UniId: int32(uniID), // UniId not used
3096 FlowId: flowID,
3097 FlowType: Downstream,
3098 AllocId: int32(allocID), // AllocId not used
3099 NetworkIntfId: int32(networkInterfaceID),
3100 GemportId: int32(gemPortID), // GemportId not used
3101 Classifier: classifierProto,
3102 Action: actionProto,
3103 Priority: int32(logicalFlow.Priority),
3104 Cookie: logicalFlow.Cookie,
3105 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08003106 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003107 return olterrors.NewErrFlowOp("add", flowID, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003108 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08003110 flowsToKVStore := f.getUpdatedFlowInfo(ctx, &downstreamflow, flowStoreCookie, "", flowID, logicalFlow.Id)
3111 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID),
3112 int32(onuID),
3113 int32(uniID),
3114 flowID, flowsToKVStore); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00003115 return olterrors.NewErrPersistence("update", "flow", flowID, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08003116 }
3117 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00003118}
3119
salmansiddiqui7ac62132019-08-22 03:58:50 +00003120func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
3121 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05303122 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 }
3124 if Dir == tp_pb.Direction_UPSTREAM {
3125 return "upstream", nil
3126 } else if Dir == tp_pb.Direction_DOWNSTREAM {
3127 return "downstream", nil
3128 }
3129 return "", nil
3130}
3131
Kent Hagermane6ff1012020-07-14 15:07:53 -04003132// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05303133func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003134 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003135 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00003136 var gemPort uint32
3137 intfID := args[IntfID]
3138 onuID := args[OnuID]
3139 uniID := args[UniID]
3140 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003141 allocID := args[AllocID]
salmansiddiqui7ac62132019-08-22 03:58:50 +00003142 if ipProto, ok := classifierInfo[IPProto]; ok {
3143 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003145 "tp-id": tpID,
3146 "alloc-id": allocID,
3147 "intf-id": intfID,
3148 "onu-id": onuID,
3149 "uni-id": uniID,
3150 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003152 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003153 tp_pb.Direction_UPSTREAM,
3154 pcp.(uint32))
3155 //Adding DHCP upstream flow
Gamze Abaka724d0852020-03-18 12:10:24 +00003156
Kent Hagermane6ff1012020-07-14 15:07:53 -04003157 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3158 logger.Warn(ctx, err)
3159 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003160 } else {
3161 //Adding DHCP upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003162 installFlowOnAllGemports(ctx, f.addDHCPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, DhcpFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 }
3164
Girish Gowdra32625212020-04-29 11:26:35 -07003165 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003166 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05303167 log.Fields{
3168 "intf-id": intfID,
3169 "onu-id": onuID,
3170 "uni-id": uniID,
3171 "classifier-info:": classifierInfo})
Esin Karamanae41e2b2019-12-17 18:13:13 +00003172 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
Esin Karamanae41e2b2019-12-17 18:13:13 +00003174 tp_pb.Direction_UPSTREAM,
3175 pcp.(uint32))
Kent Hagermane6ff1012020-07-14 15:07:53 -04003176 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3177 logger.Warn(ctx, err)
3178 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00003179 } else {
3180 //Adding IGMP upstream flow to all gem ports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003181 installFlowOnAllGemports(ctx, f.addIGMPTrapFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, IgmpFlow, Upstream, tpID)
Esin Karamanae41e2b2019-12-17 18:13:13 +00003182 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003183 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003185 return
3186 }
3187 } else if ethType, ok := classifierInfo[EthType]; ok {
3188 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003189 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003190 "intf-id": intfID,
3191 "onu-id": onuID,
3192 "uni-id": uniID,
3193 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003194 var vlanID uint32
3195 if val, ok := classifierInfo[VlanVid]; ok {
3196 vlanID = (val.(uint32)) & VlanvIDMask
3197 } else {
3198 vlanID = DefaultMgmtVlan
3199 }
3200 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003201 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003202 tp_pb.Direction_UPSTREAM,
3203 pcp.(uint32))
3204
Kent Hagermane6ff1012020-07-14 15:07:53 -04003205 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID); err != nil {
3206 logger.Warn(ctx, err)
3207 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003208 } else {
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003209 installFlowOnAllGemports(ctx, nil, f.addEAPOLFlow, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, EapolFlow, Upstream, tpID, vlanID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210 }
3211 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003212 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003214 "intf-id": intfID,
3215 "onu-id": onuID,
3216 "uni-id": uniID,
3217 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003218 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003219 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003220 tp_pb.Direction_UPSTREAM,
3221 pcp.(uint32))
3222 //Adding HSIA upstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003223 if err := f.addUpstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3224 logger.Warn(ctx, err)
3225 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003226 } else {
3227 //Adding HSIA upstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003228 installFlowOnAllGemports(ctx, f.addUpstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Upstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003229 }
3230 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003231 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003232 "intf-id": intfID,
3233 "onu-id": onuID,
3234 "uni-id": uniID,
3235 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00003236 if pcp, ok := classifierInfo[VlanPcp]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
aishwaryarana01d9f985f2019-09-03 15:41:40 -05003238 tp_pb.Direction_DOWNSTREAM,
salmansiddiqui7ac62132019-08-22 03:58:50 +00003239 pcp.(uint32))
3240 //Adding HSIA downstream flow
Kent Hagermane6ff1012020-07-14 15:07:53 -04003241 if err := f.addDownstreamDataFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID); err != nil {
3242 logger.Warn(ctx, err)
3243 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003244 } else {
3245 //Adding HSIA downstream flow to all gemports
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00003246 installFlowOnAllGemports(ctx, f.addDownstreamDataFlow, nil, args, classifierInfo, actionInfo, flow, gemPorts, TpInst, HsiaFlow, Downstream, tpID)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003247 }
3248 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05303250 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003251 "intf-id": intfID,
3252 "onu-id": onuID,
3253 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05303254 "classifier": classifierInfo,
3255 "action": actionInfo,
3256 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003257 return
3258 }
3259 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003260 go func() {
3261 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
3262 logger.Warn(ctx, err)
3263 }
3264 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003265}
3266
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003267func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(ctx context.Context, gemPK gemPortKey) (bool, error) {
3268 if f.perGemPortLock.TryLock(gemPK) {
3269 flowIDList := f.flowsUsedByGemPort[gemPK]
3270 f.perGemPortLock.Unlock(gemPK)
3271 return len(flowIDList) > 1, nil
3272 }
3273 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3274 log.Fields{
3275 "device-id": f.deviceHandler.device.Id,
3276 "key": gemPK,
3277 })
3278 return false, olterrors.NewErrAdapter("failed-to-acquire-per-gem-port-lock", log.Fields{
3279 "device-id": f.deviceHandler.device.Id,
3280 "key": gemPK,
3281 }, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003282}
3283
npujarec5762e2020-01-01 14:08:48 +05303284func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3285 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003286 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3287 for _, currentGemPort := range currentGemPorts {
3288 for _, tpGemPort := range tpGemPorts {
3289 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3290 return true, currentGemPort
3291 }
3292 }
3293 }
Girish Gowdra54934262019-11-13 14:19:55 +05303294 if tpInst.InstanceCtrl.Onu == "single-instance" {
3295 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Kent Hagermane6ff1012020-07-14 15:07:53 -04003296 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, uint32(onuID), uint32(uniID), tpID); err != nil {
3297 logger.Warn(ctx, err)
3298 }
3299 if err := f.DeleteTechProfileInstance(ctx, ponIntf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
3300 logger.Warn(ctx, err)
3301 }
Girish Gowdra54934262019-11-13 14:19:55 +05303302
3303 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3304 // still be used on other uni ports.
3305 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3306 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003307 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003308 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303309 for i := 0; i < len(tpInstances); i++ {
3310 tpI := tpInstances[i]
3311 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303312 for _, tpGemPort := range tpGemPorts {
3313 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003314 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303315 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303316 }
3317 }
3318 }
3319 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003320 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003321 return false, 0
3322}
3323
Neha Sharma96b7bf22020-06-15 10:37:32 +00003324func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003325 for _, field := range flows.GetOfbFields(flow) {
3326 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003327 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003328 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003329 } else if field.Type == flows.ETH_DST {
3330 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003331 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003332 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003333 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003334 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003335 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003336 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003337 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003338 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303339 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003340 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003341 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003342 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003343 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003344 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003345 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003346 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003347 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003348 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003349 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003350 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003351 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003352 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003353 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003354 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003355 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003356 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003357 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003358 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003359 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003360 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003361 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003362 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003363 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003364 return
3365 }
3366 }
3367}
3368
Neha Sharma96b7bf22020-06-15 10:37:32 +00003369func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003370 for _, action := range flows.GetActions(flow) {
3371 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003372 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003373 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003374 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003375 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003376 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003377 }
Scott Baker355d1742019-10-24 10:57:52 -07003378 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003379 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003380 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003381 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003382 if out := action.GetPush(); out != nil {
3383 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003384 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003385 } else {
3386 actionInfo[PushVlan] = true
3387 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003388 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303389 log.Fields{
3390 "push-tpid": actionInfo[TPID].(uint32),
3391 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003392 }
3393 }
Scott Baker355d1742019-10-24 10:57:52 -07003394 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003395 if out := action.GetSetField(); out != nil {
3396 if field := out.GetField(); field != nil {
3397 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003398 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003399 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003400 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3401 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003402 }
3403 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003404 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003405 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003406 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003407 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003408 }
3409 }
3410 return nil
3411}
3412
Neha Sharma96b7bf22020-06-15 10:37:32 +00003413func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003414 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003415 fieldtype := ofbField.GetType()
3416 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003417 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3418 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003419 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003420 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003421 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003422 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003423 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3424 pcp := ofbField.GetVlanPcp()
3425 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003426 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003427 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003428 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003429 }
3430 }
3431}
3432
Neha Sharma96b7bf22020-06-15 10:37:32 +00003433func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003434 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003435 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003436 } else {
3437 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003438 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003439 }
3440}
3441
Neha Sharma96b7bf22020-06-15 10:37:32 +00003442func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003443 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003444 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003445 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3446 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003447 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003448 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003449 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303450 log.Fields{
3451 "newinport": classifierInfo[InPort].(uint32),
3452 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003453 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303454 return olterrors.NewErrNotFound("child-in-port",
3455 log.Fields{
3456 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3457 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003458 }
3459 }
3460 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003461 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003462 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003463 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003464 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003465 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003466 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303467 log.Fields{
3468 "newoutport": actionInfo[Output].(uint32),
3469 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003470 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303471 return olterrors.NewErrNotFound("out-port",
3472 log.Fields{
3473 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3474 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003475 }
3476 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3477 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003478 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003479 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003480 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303481 log.Fields{
3482 "newinport": actionInfo[Output].(uint32),
3483 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003484 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303485 return olterrors.NewErrNotFound("nni-port",
3486 log.Fields{
3487 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3488 "in-port": classifierInfo[InPort].(uint32),
3489 "out-port": actionInfo[Output].(uint32),
3490 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003491 }
3492 }
3493 }
3494 return nil
3495}
Gamze Abakafee36392019-10-03 11:17:24 +00003496
Neha Sharma96b7bf22020-06-15 10:37:32 +00003497func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003498 /* Metadata 8 bytes:
3499 Most Significant 2 Bytes = Inner VLAN
3500 Next 2 Bytes = Tech Profile ID(TPID)
3501 Least Significant 4 Bytes = Port ID
3502 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3503 subscriber related flows.
3504 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003505 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003506 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003507 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003508 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003509 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003510 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003511}
3512
3513func appendUnique(slice []uint32, item uint32) []uint32 {
3514 for _, sliceElement := range slice {
3515 if sliceElement == item {
3516 return slice
3517 }
3518 }
3519 return append(slice, item)
3520}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303521
3522// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003523func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303524
3525 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3526 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003527 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003528 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003529 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003530 log.Fields{
3531 "port-number": action[Output].(uint32),
3532 "error": err})
3533 return uint32(0), err
3534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003535 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303536 return intfID, nil
3537 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003538 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003539 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003540 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003541 log.Fields{
3542 "port-number": action[Output].(uint32),
3543 "error": err})
3544 return uint32(0), err
3545 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003546 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303547 return intfID, nil
3548 }
3549 return uint32(0), nil
3550}
3551
3552// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003553func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3554 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3555 if err != nil {
3556 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3557 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3558 return
3559 }
3560 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003561
3562 f.onuGemInfoLock.Lock()
3563 defer f.onuGemInfoLock.Unlock()
3564
Matt Jeanneret1719a072019-12-20 14:50:14 -05003565 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303566 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003567 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003568 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 +05303569 log.Fields{
3570 "pktinkey": pktInkey,
3571 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003572 return
3573 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303574 }
Matt Jeanneret1719a072019-12-20 14:50:14 -05003575 f.packetInGemPort[pktInkey] = gemPort
3576
npujarec5762e2020-01-01 14:08:48 +05303577 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003578 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 +05303579 log.Fields{
3580 "pktinkey": pktInkey,
3581 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303582}
3583
Esin Karaman7fb80c22020-07-16 14:23:33 +00003584//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3585func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3586 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003587 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003588 return 0, 0, errors.New("invalid packet length")
3589 }
3590 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3591 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3592
3593 var index int8
3594 if outerEthType == 0x8100 {
3595 if innerEthType == 0x8100 {
3596 // q-in-q 802.1ad or 802.1q double tagged packet.
3597 // get the inner vlanId
3598 index = 18
3599 } else {
3600 index = 14
3601 }
3602 priority := (packet[index] >> 5) & 0x7
3603 //13 bits composes vlanId value
3604 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3605 return vlan, priority, nil
3606 }
3607 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3608 return 0, 0, nil
3609}
3610
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303611// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303612func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003613
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003614 f.onuGemInfoLock.Lock()
3615 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003616
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303617 onugem := f.onuGemInfo[intfID]
3618 for idx, onu := range onugem {
3619 if onu.OnuID == onuID {
3620 for _, uni := range onu.UniPorts {
3621 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003622 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 +05303623 return
3624 }
3625 }
3626 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
3627 f.onuGemInfo[intfID] = onugem
3628 }
3629 }
npujarec5762e2020-01-01 14:08:48 +05303630 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003631
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303632}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303633
npujarec5762e2020-01-01 14:08:48 +05303634func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3635 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303636 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003637 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303638 return
3639 }
3640 for gem, FlowIDs := range flowIDsList {
3641 gemPK := gemPortKey{intf, uint32(gem)}
Matteo Scandolo738c52a2020-08-03 11:14:22 -07003642 if f.perGemPortLock.TryLock(gemPK) {
3643 f.flowsUsedByGemPort[gemPK] = FlowIDs
3644 f.perGemPortLock.Unlock(gemPK)
3645 } else {
3646 logger.Error(ctx, "failed-to-acquire-per-gem-port-lock",
3647 log.Fields{
3648 "intf-id": intf,
3649 "device-id": f.deviceHandler.device.Id,
3650 "key": gemPK,
3651 })
3652 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303653 }
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303654}
Esin Karamanccb714b2019-11-29 15:02:06 +00003655
Girish Gowdra9602eb42020-09-09 15:50:39 -07003656//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3657// clears resources reserved for this multicast flow
3658func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) {
3659 classifierInfo := make(map[string]interface{})
3660 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3661 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3662
Esin Karamanccb714b2019-11-29 15:02:06 +00003663 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003664 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 +00003665 return
3666 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003667
3668 var onuID = int32(NoneOnuID)
3669 var uniID = int32(NoneUniID)
3670 var flowID uint32
3671
3672 flowIds := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, networkInterfaceID, onuID, uniID)
3673
3674 for _, flowID = range flowIds {
3675 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
3676 if flowInfo == nil {
3677 logger.Debugw(ctx, "no-multicast-flowinfo-found-in-the-kv-store",
3678 log.Fields{
3679 "intf": networkInterfaceID,
3680 "onu-id": onuID,
3681 "uni-id": uniID,
3682 "flow-id": flowID})
3683 continue
Esin Karamanccb714b2019-11-29 15:02:06 +00003684 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003685 updatedFlows := *flowInfo
3686 for i, storedFlow := range updatedFlows {
3687 if flow.Id == storedFlow.LogicalFlowID {
3688 removeFlowMessage := openoltpb2.Flow{FlowId: storedFlow.Flow.FlowId, FlowType: storedFlow.Flow.FlowType}
3689 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3690 log.Fields{
3691 "flow": storedFlow,
3692 "flow-id": flow.Id,
3693 "device-id": f.deviceHandler.device.Id})
3694 //remove from device
3695 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3696 // DKB
3697 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3698 log.Fields{
3699 "flow-id": flow.Id,
3700 "error": err})
3701 return
3702 }
3703 logger.Infow(ctx, "multicast-flow-removed-from-device-successfully", log.Fields{"flow-id": flow.Id})
3704 //Remove the Flow from FlowInfo
3705 updatedFlows = append(updatedFlows[:i], updatedFlows[i+1:]...)
3706 if err := f.updateFlowInfoToKVStore(ctx, int32(networkInterfaceID), NoneOnuID, NoneUniID, flowID, &updatedFlows); err != nil {
3707 logger.Errorw(ctx, "failed-to-delete-multicast-flow-from-the-kv-store",
3708 log.Fields{"flow": storedFlow,
3709 "err": err})
3710 return
3711 }
3712 //release flow id
3713 logger.Debugw(ctx, "releasing-multicast-flow-id",
3714 log.Fields{"flow-id": flowID,
3715 "interfaceID": networkInterfaceID})
3716 f.resourceMgr.FreeFlowID(ctx, uint32(networkInterfaceID), NoneOnuID, NoneUniID, flowID)
3717 }
3718 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003719 }
3720}
3721
Girish Gowdra9602eb42020-09-09 15:50:39 -07003722func (f *OpenOltFlowMgr) incrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
3723 inPort, outPort := getPorts(flow)
3724 logger.Debugw(ctx, "increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3725 if inPort != InvalidPort && outPort != InvalidPort {
3726 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3727 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3728 logger.Debugw(ctx, "increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3729
3730 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3731 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3732 flowRemoveData, ok := f.pendingFlowRemoveDataPerSubscriber[key]
3733 if !ok {
3734 flowRemoveData = pendingFlowRemoveData{
3735 pendingFlowRemoveCount: 0,
3736 allFlowsRemoved: make(chan struct{}),
3737 }
3738 }
3739 flowRemoveData.pendingFlowRemoveCount++
3740 f.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
3741
3742 logger.Debugw(ctx, "current-flow-remove-count–increment",
3743 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3744 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
Esin Karamanccb714b2019-11-29 15:02:06 +00003745 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003746}
3747
Girish Gowdra9602eb42020-09-09 15:50:39 -07003748func (f *OpenOltFlowMgr) decrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
3749 inPort, outPort := getPorts(flow)
3750 logger.Debugw(ctx, "decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3751 if inPort != InvalidPort && outPort != InvalidPort {
3752 _, intfID, onuID, uniID := ExtractAccessFromFlow(uint32(inPort), uint32(outPort))
3753 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3754 logger.Debugw(ctx, "decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3755
3756 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3757 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3758 if val, ok := f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3759 logger.Fatalf(ctx, "flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3760 } else {
3761 if val.pendingFlowRemoveCount > 0 {
3762 val.pendingFlowRemoveCount--
3763 }
3764 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
3765 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3766 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
3767 // If all flow removes have finished, then close the channel to signal the receiver
3768 // to go ahead with flow adds.
3769 if val.pendingFlowRemoveCount == 0 {
3770 close(val.allFlowsRemoved)
3771 delete(f.pendingFlowRemoveDataPerSubscriber, key)
3772 return
3773 }
3774 f.pendingFlowRemoveDataPerSubscriber[key] = val
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003775 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003776 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003777}
3778
3779func (f *OpenOltFlowMgr) waitForFlowRemoveToFinish(ctx context.Context, flow *ofp.OfpFlowStats) {
3780 var flowRemoveData pendingFlowRemoveData
3781 var ok bool
3782 inPort, outPort := getPorts(flow)
3783 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3784 if inPort != InvalidPort && outPort != InvalidPort {
3785 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3786 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3787 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3788
3789 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
3790 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3791 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3792 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3793 return
3794 }
3795 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3796
3797 // Wait for all flow removes to finish first
3798 <-flowRemoveData.allFlowsRemoved
3799
3800 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3801 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003802}