blob: b936a90bdde633962742dc0db97e972f8c4df597 [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"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070025 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
26 "github.com/opencord/voltha-lib-go/v4/pkg/log"
27 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080028 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-protos/v4/go/common"
30 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
31 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
32 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
33 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
34 "github.com/opencord/voltha-protos/v4/go/voltha"
Girish Gowdra9602eb42020-09-09 15:50:39 -070035 "strings"
36 "sync"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Girish Gowdra3d633032019-12-10 16:37:05 +053038 "github.com/EagleChen/mapmutex"
Thomas Lee S94109f12020-03-03 16:39:29 +053039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053042)
43
44const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070045 //IPProtoDhcp flow category
46 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053047
Girish Gowdraa09aeab2020-09-14 16:30:52 -070048 //IgmpProto proto value
49 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050
51 //EapEthType eapethtype value
52 EapEthType = 0x888e
53 //LldpEthType lldp ethtype value
54 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000055 //IPv4EthType IPv4 ethernet type value
56 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057
Andrea Campanella7acc0b92020-02-14 09:20:49 +010058 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
59 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 //DefaultMgmtVlan default vlan value
62 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053063
manikkaraj kbf256be2019-03-25 00:13:48 +053064 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065
David K. Bainbridge82efc492019-09-04 09:57:11 -070066 //Upstream constant
67 Upstream = "upstream"
68 //Downstream constant
69 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000070 //Multicast constant
71 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 //PacketTagType constant
73 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 //Untagged constant
75 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //SingleTag constant
77 SingleTag = "single_tag"
78 //DoubleTag constant
79 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053080
81 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082
83 //EthType constant
84 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000085 //EthDst constant
86 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //TPID constant
88 TPID = "tpid"
89 //IPProto constant
90 IPProto = "ip_proto"
91 //InPort constant
92 InPort = "in_port"
93 //VlanVid constant
94 VlanVid = "vlan_vid"
95 //VlanPcp constant
96 VlanPcp = "vlan_pcp"
97
98 //UDPDst constant
99 UDPDst = "udp_dst"
100 //UDPSrc constant
101 UDPSrc = "udp_src"
102 //Ipv4Dst constant
103 Ipv4Dst = "ipv4_dst"
104 //Ipv4Src constant
105 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700106 //Metadata constant
107 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 //TunnelID constant
109 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Output constant
111 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000112 //GroupID constant
113 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 // Actions
115
116 //PopVlan constant
117 PopVlan = "pop_vlan"
118 //PushVlan constant
119 PushVlan = "push_vlan"
120 //TrapToHost constant
121 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400122 //MaxMeterBand constant
123 MaxMeterBand = 2
124 //VlanPCPMask contant
125 VlanPCPMask = 0xFF
126 //VlanvIDMask constant
127 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000128 //IntfID constant
129 IntfID = "intfId"
130 //OnuID constant
131 OnuID = "onuId"
132 //UniID constant
133 UniID = "uniId"
134 //PortNo constant
135 PortNo = "portNo"
136 //AllocID constant
137 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138
139 //NoneOnuID constant
140 NoneOnuID = -1
141 //NoneUniID constant
142 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700143
144 // MapMutex
145 maxRetry = 300
146 maxDelay = 100000000
147 baseDelay = 10000000
148 factor = 1.1
149 jitter = 0.2
manikkaraj kbf256be2019-03-25 00:13:48 +0530150
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700151 bitMapPrefix = "0b"
152 pbit1 = '1'
153)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400154
Girish Gowdra3d633032019-12-10 16:37:05 +0530155type tpLockKey struct {
156 intfID uint32
157 onuID uint32
158 uniID uint32
159}
160
Gamze Abakafee36392019-10-03 11:17:24 +0000161type schedQueue struct {
162 direction tp_pb.Direction
163 intfID uint32
164 onuID uint32
165 uniID uint32
166 tpID uint32
167 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700168 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000169 meterID uint32
170 flowMetadata *voltha.FlowMetadata
171}
172
Girish Gowdra9602eb42020-09-09 15:50:39 -0700173// pendingFlowRemoveDataKey is key to pendingFlowRemoveDataPerSubscriber map
174type pendingFlowRemoveDataKey struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178}
179
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700180// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
181type subscriberDataPathFlowIDKey struct {
182 intfID uint32
183 onuID uint32
184 uniID uint32
185 direction string
186 tpID uint32
187}
188
Girish Gowdra9602eb42020-09-09 15:50:39 -0700189// pendingFlowRemoveData is value stored in pendingFlowRemoveDataPerSubscriber map
190// This holds the number of pending flow removes and also a signal channel to
191// to indicate the receiver when all flow removes are handled
192type pendingFlowRemoveData struct {
193 pendingFlowRemoveCount uint32
194 allFlowsRemoved chan struct{}
Esin Karamanccb714b2019-11-29 15:02:06 +0000195}
196
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700197//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530198type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700199 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
200 techprofile map[uint32]tp.TechProfileIf
201 deviceHandler *DeviceHandler
202 grpMgr *OpenOltGroupMgr
203 resourceMgr *rsrcMgr.OpenOltResourceMgr
204
205 onuIdsLock sync.RWMutex // TODO: Do we need this?
206
207 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
208 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
209
210 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
211 packetInGemPortLock sync.RWMutex
212
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700213 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700214 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700215 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700216 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700217
Girish Gowdra3d633032019-12-10 16:37:05 +0530218 // The mapmutex.Mutex can be fine tuned to use mapmutex.NewCustomizedMapMutex
Girish Gowdra9602eb42020-09-09 15:50:39 -0700219 perUserFlowHandleLock *mapmutex.Mutex
220
221 // pendingFlowRemoveDataPerSubscriber map is used to maintain the context on a per
222 // subscriber basis for the number of pending flow removes. This data is used
223 // to process all the flow removes for a subscriber before handling flow adds.
224 // Interleaving flow delete and flow add processing has known to cause PON resource
225 // management contentions on a per subscriber bases, so we need ensure ordering.
226 pendingFlowRemoveDataPerSubscriber map[pendingFlowRemoveDataKey]pendingFlowRemoveData
227 pendingFlowRemoveDataPerSubscriberLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228
229 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
230 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
231 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
232 subscriberDataPathFlowIDMapLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530233}
234
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700235//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700236func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000237 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530239 var err error
240 var idx uint32
241
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700243 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000245 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000246 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
247 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530248 return nil
249 }
William Kurkian740a09c2019-10-23 17:07:38 -0400250 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdra9602eb42020-09-09 15:50:39 -0700251 flowMgr.pendingFlowRemoveDataPerSubscriberLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700252 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530253 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700254 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700255 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700256 flowMgr.perUserFlowHandleLock = mapmutex.NewCustomizedMapMutex(maxRetry, maxDelay, baseDelay, factor, jitter)
Girish Gowdra9602eb42020-09-09 15:50:39 -0700257 flowMgr.pendingFlowRemoveDataPerSubscriber = make(map[pendingFlowRemoveDataKey]pendingFlowRemoveData)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700258 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
259 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530260 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700261 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
262 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 //Load flowID list per gem map per interface from the kvstore.
265 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000266 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700267 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700268 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000269 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530270 return &flowMgr
271}
272
Kent Hagermane6ff1012020-07-14 15:07:53 -0400273func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
275 // Flow is not replicated in this case, we need to register the flow for a single gem-port
276 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
277 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
278 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
279 for _, gemPort := range deviceFlow.PbitToGemport {
280 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
281 return err
282 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700283 }
Gamze Abakafee36392019-10-03 11:17:24 +0000284 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700285 return nil
286}
287
288func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
289 f.flowsUsedByGemPortKey.Lock()
290 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
291 if !ok {
292 flowIDList = []uint64{flowFromCore.Id}
293 }
294 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
295 f.flowsUsedByGemPort[gemPortID] = flowIDList
296 f.flowsUsedByGemPortKey.Unlock()
297
298 // update the flowids for a gem to the KVstore
299 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400300}
301
Girish Gowdra9602eb42020-09-09 15:50:39 -0700302func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000303 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200304 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000305 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530306 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700307 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530308
Neha Sharma96b7bf22020-06-15 10:37:32 +0000309 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530310 "device-id": f.deviceHandler.device.Id,
311 "intf-id": intfID,
312 "onu-id": onuID,
313 "uni-id": uniID,
314 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700315 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530316 "action": actionInfo,
317 "usmeter-iD": UsMeterID,
318 "dsmeter-iD": DsMeterID,
319 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400320 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
321 // is because the flow is an NNI flow and there would be no onu resources associated with it
322 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400323 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200324 cause := "no-onu-id-for-flow"
325 fields := log.Fields{
326 "onu": onuID,
327 "port-no": portNo,
328 "classifer": classifierInfo,
329 "action": actionInfo,
330 "device-id": f.deviceHandler.device.Id}
331 logger.Errorw(ctx, cause, fields)
332 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530333 }
334
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700335 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530337 "uni": uni,
338 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530339
340 tpLockMapKey := tpLockKey{intfID, onuID, uniID}
341 if f.perUserFlowHandleLock.TryLock(tpLockMapKey) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000342 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530343 "device-id": f.deviceHandler.device.Id,
344 "intf-id": intfID,
345 "onu-id": onuID,
346 "uni-id": uniID,
347 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700348 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530349 "action": actionInfo,
350 "usmeter-id": UsMeterID,
351 "dsmeter-id": DsMeterID,
352 "tp-id": TpID})
npujarec5762e2020-01-01 14:08:48 +0530353 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra3d633032019-12-10 16:37:05 +0530354 if allocID == 0 || gemPorts == nil || TpInst == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
Girish Gowdra3d633032019-12-10 16:37:05 +0530356 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
Andrea Campanellabfe08432020-09-11 17:07:03 +0200357 return olterrors.NewErrNotFound(
358 "alloc-id-gem-ports-tp-unavailable",
359 nil, nil)
Girish Gowdra3d633032019-12-10 16:37:05 +0530360 }
361 args := make(map[string]uint32)
362 args[IntfID] = intfID
363 args[OnuID] = onuID
364 args[UniID] = uniID
365 args[PortNo] = portNo
366 args[AllocID] = allocID
367
368 /* Flows can be added specific to gemport if p-bits are received.
369 * If no pbit mentioned then adding flows for all gemports
370 */
npujarec5762e2020-01-01 14:08:48 +0530371 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
Girish Gowdra3d633032019-12-10 16:37:05 +0530372 f.perUserFlowHandleLock.Unlock(tpLockMapKey)
373 } else {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200374 cause := "failed-to-acquire-per-user-flow-handle-lock"
375 fields := log.Fields{
376 "intf-id": intfID,
377 "onu-id": onuID,
378 "uni-id": uniID,
379 "flow-id": flow.Id,
380 "flow-cookie": flow.Cookie,
381 "device-id": f.deviceHandler.device.Id}
382 logger.Errorw(ctx, cause, fields)
383 return olterrors.NewErrAdapter(cause, fields, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 }
Andrea Campanellabfe08432020-09-11 17:07:03 +0200385 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530386}
387
salmansiddiqui7ac62132019-08-22 03:58:50 +0000388// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530389func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400390
Neha Sharma96b7bf22020-06-15 10:37:32 +0000391 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530392 log.Fields{"dir": sq.direction,
393 "intf-id": sq.intfID,
394 "onu-id": sq.onuID,
395 "uni-id": sq.uniID,
396 "tp-id": sq.tpID,
397 "meter-id": sq.meterID,
398 "tp-inst": sq.tpInst,
399 "flowmetadata": sq.flowMetadata,
400 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401
Gamze Abakafee36392019-10-03 11:17:24 +0000402 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000403 if err != nil {
404 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 }
406
407 /* Lets make a simple assumption that if the meter-id is present on the KV store,
408 * then the scheduler and queues configuration is applied on the OLT device
409 * in the given direction.
410 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000411
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530413 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400414 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530415 return olterrors.NewErrNotFound("meter",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000421
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000423 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000424 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400425 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530427 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800428 "unsupported": "meter-id",
429 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530430 "meter-id-in-flow": sq.meterID,
431 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000433
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{
436 "meter-id": sq.meterID,
437 "direction": Direction,
438 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Gamze Abakafee36392019-10-03 11:17:24 +0000440 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000442 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000443 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
446 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530447 return olterrors.NewErrNotFound("scheduler-config",
448 log.Fields{
449 "intf-id": sq.intfID,
450 "direction": sq.direction,
451 "tp-inst": sq.tpInst,
452 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453 }
454
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000456 if sq.flowMetadata != nil {
457 for _, meter := range sq.flowMetadata.Meters {
458 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000460 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530461 log.Fields{"meterConfig": meterConfig,
462 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400463 break
464 }
465 }
466 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400468 }
469 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530470 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800471 "reason": "Could-not-get-meterbands-from-flowMetadata",
472 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530473 "meter-id": sq.meterID,
474 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530477 log.Fields{"Bands": meterConfig.Bands,
478 "meter-id": sq.meterID,
479 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "reason": "Invalid-number-of-bands-in-meter",
482 "meterband-count": len(meterConfig.Bands),
483 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
487 cir := meterConfig.Bands[0].Rate
488 cbs := meterConfig.Bands[0].BurstSize
489 eir := meterConfig.Bands[1].Rate
490 ebs := meterConfig.Bands[1].BurstSize
491 pir := cir + eir
492 pbs := cbs + ebs
493 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
494
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700495 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000496 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400497
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700498 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530499 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 }
504
salmansiddiqui7ac62132019-08-22 03:58:50 +0000505 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400506 * store the meter id on the KV store, for further reference.
507 */
npujarec5762e2020-01-01 14:08:48 +0530508 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 +0530509 return olterrors.NewErrAdapter("failed-updating-meter-id",
510 log.Fields{"onu-id": sq.onuID,
511 "meter-id": sq.meterID,
512 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000514 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530515 log.Fields{"direction": Direction,
516 "Meter": meterConfig,
517 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400518 return nil
519}
520
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700521func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000523
524 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530525 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
526 log.Fields{"intf-id": sq.intfID,
527 "direction": sq.direction,
528 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000529 }
530
Neha Sharma96b7bf22020-06-15 10:37:32 +0000531 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530532 log.Fields{
533 "direction": sq.direction,
534 "TrafficScheds": TrafficSched,
535 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530536 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537 IntfId: sq.intfID, OnuId: sq.onuID,
538 UniId: sq.uniID, PortNo: sq.uniPort,
539 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000540 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000542 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530543 "direction": sq.direction,
544 "traffic-queues": trafficQueues,
545 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000546
547 // On receiving the CreateTrafficQueues request, the driver should create corresponding
548 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000549 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530550 log.Fields{"direction": sq.direction,
551 "traffic-queues": trafficQueues,
552 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530553 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000554 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
555 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000556 TrafficQueues: trafficQueues,
557 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530558 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000560 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530561 "direction": sq.direction,
562 "traffic-queues": trafficQueues,
563 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564
Esin Karamanccb714b2019-11-29 15:02:06 +0000565 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000566 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700568 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 //assumed that there is only one queue per PON for the multicast service
570 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
571 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000573 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700574 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000575 gemPortID: multicastQueuePerPonPort.GemportId,
576 servicePriority: multicastQueuePerPonPort.Priority,
577 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700578 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400580 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
581 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
582 return err
583 }
Shrey Baid26912972020-04-16 21:02:31 +0530584
Neha Sharma96b7bf22020-06-15 10:37:32 +0000585 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000586 }
587 }
588 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 return nil
590}
591
salmansiddiqui7ac62132019-08-22 03:58:50 +0000592// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530593func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400594
595 var Direction string
596 var SchedCfg *tp_pb.SchedulerConfig
597 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000598 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530599 log.Fields{
600 "direction": sq.direction,
601 "intf-id": sq.intfID,
602 "onu-id": sq.onuID,
603 "uni-id": sq.uniID,
604 "uni-port": sq.uniPort,
605 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000606 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000607 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000609 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 Direction = "downstream"
612 }
613
Girish Kumar8f73fe02019-12-09 13:19:37 +0000614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530615 return olterrors.NewErrNotFound("scheduler-config",
616 log.Fields{
617 "int-id": sq.intfID,
618 "direction": sq.direction,
619 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000620 }
621
npujarec5762e2020-01-01 14:08:48 +0530622 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400623 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530624 return olterrors.NewErrNotFound("meter",
625 log.Fields{
626 "onu-id": sq.onuID,
627 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400628 }
629 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000630 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530631 log.Fields{
632 "direction": Direction,
633 "intf-id": sq.intfID,
634 "onu-id": sq.onuID,
635 "uni-id": sq.uniID,
636 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400637 return nil
638 }
639 cir := KVStoreMeter.Bands[0].Rate
640 cbs := KVStoreMeter.Bands[0].BurstSize
641 eir := KVStoreMeter.Bands[1].Rate
642 ebs := KVStoreMeter.Bands[1].BurstSize
643 pir := cir + eir
644 pbs := cbs + ebs
645
646 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
647
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700648 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000649 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000650
Neha Sharma96b7bf22020-06-15 10:37:32 +0000651 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000652 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530653 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
654 log.Fields{
655 "intf-id": sq.intfID,
656 "direction": sq.direction,
657 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000658 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400659
npujarec5762e2020-01-01 14:08:48 +0530660 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000661 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
662 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficQueues: TrafficQueues,
664 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000665 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530666 log.Fields{
667 "intf-id": sq.intfID,
668 "traffic-queues": TrafficQueues,
669 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000671 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530672 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000673 IntfId: sq.intfID, OnuId: sq.onuID,
674 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000676 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530677 log.Fields{
678 "intf-id": sq.intfID,
679 "traffic-schedulers": TrafficSched}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
681
Neha Sharma96b7bf22020-06-15 10:37:32 +0000682 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000683
684 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 * delete the meter id on the KV store.
686 */
npujarec5762e2020-01-01 14:08:48 +0530687 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530689 return olterrors.NewErrAdapter("unable-to-remove-meter",
690 log.Fields{
691 "onu": sq.onuID,
692 "meter": KVStoreMeter.MeterId,
693 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400694 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000695 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530696 log.Fields{
697 "meter-id": KVStoreMeter.MeterId,
698 "dir": Direction,
699 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 return err
701}
702
Gamze Abakafee36392019-10-03 11:17:24 +0000703// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700704func (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 +0000705 var allocIDs []uint32
706 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530707 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530708 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000709 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000710
npujarec5762e2020-01-01 14:08:48 +0530711 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
712 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400713
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530715
Neha Sharma96b7bf22020-06-15 10:37:32 +0000716 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530717 "intf-id": intfID,
718 "onu-id": onuID,
719 "uni-id": uniID,
720 "device-id": f.deviceHandler.device.Id,
721 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530722
Manikkaraj kb1d51442019-07-23 10:41:02 -0400723 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530724 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000725 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000726 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530727 log.Fields{
728 "path": tpPath,
729 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530730 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000731 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530732 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530734 log.Fields{
735 "error": err,
736 "tp-id": TpID,
737 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000738 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530739 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400740 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
741 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
742 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530743 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000744 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530745 log.Fields{
746 "uni": uni,
747 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530748 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530749 }
Gamze Abakafee36392019-10-03 11:17:24 +0000750
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700751 switch tpInst := techProfileInstance.(type) {
752 case *tp.TechProfile:
753 if UsMeterID != 0 {
754 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
755 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
756 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000757 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700758 log.Fields{
759 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700760 "onu-id": onuID,
761 "uni-id": uniID,
762 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700763 "meter-id": UsMeterID,
764 "device-id": f.deviceHandler.device.Id})
765 return 0, nil, nil
766 }
767 }
768 if DsMeterID != 0 {
769 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
770 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
771 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700773 log.Fields{
774 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700775 "onu-id": onuID,
776 "uni-id": uniID,
777 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700778 "meter-id": DsMeterID,
779 "device-id": f.deviceHandler.device.Id})
780 return 0, nil, nil
781 }
782 }
783 allocID := tpInst.UsScheduler.AllocID
784 for _, gem := range tpInst.UpstreamGemPortAttributeList {
785 gemPortIDs = append(gemPortIDs, gem.GemportID)
786 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700787 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000788
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700789 if tpInstanceExists {
790 return allocID, gemPortIDs, techProfileInstance
791 }
792
793 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700794 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700795 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000796 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700797 log.Fields{
798 "alloc-ids": allocIDs,
799 "gemports": allgemPortIDs,
800 "device-id": f.deviceHandler.device.Id})
801 // Send Tconts and GEM ports to KV store
802 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530803 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700804 case *tp.EponProfile:
805 // CreateSchedulerQueues for EPON needs to be implemented here
806 // when voltha-protos for EPON is completed.
807 allocID := tpInst.AllocID
808 for _, gem := range tpInst.UpstreamQueueAttributeList {
809 gemPortIDs = append(gemPortIDs, gem.GemportID)
810 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700811 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700812
813 if tpInstanceExists {
814 return allocID, gemPortIDs, techProfileInstance
815 }
816
817 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700818 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700819 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000820 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700821 log.Fields{
822 "alloc-ids": allocIDs,
823 "gemports": allgemPortIDs,
824 "device-id": f.deviceHandler.device.Id})
825 // Send Tconts and GEM ports to KV store
826 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
827 return allocID, gemPortIDs, techProfileInstance
828 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000829 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700830 log.Fields{
831 "tpInst": tpInst})
832 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530833 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530834}
835
npujarec5762e2020-01-01 14:08:48 +0530836func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530837
Neha Sharma96b7bf22020-06-15 10:37:32 +0000838 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530839 log.Fields{
840 "intf-id": intfID,
841 "onu-id": onuID,
842 "uni-id": uniID,
843 "alloc-id": allocID,
844 "gemport-ids": gemPortIDs,
845 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530846 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530847 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000848 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 +0530849 }
npujarec5762e2020-01-01 14:08:48 +0530850 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 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 +0530852 }
npujarec5762e2020-01-01 14:08:48 +0530853 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 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 +0530855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 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 -0400857 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530858 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400859 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530860}
861
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000863 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530864 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000865 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700866 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400867 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530869 log.Fields{
870 "intf-id": intfID,
871 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530872 }
873 }
874 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400875 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530876 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530877 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800878 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530879 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
880 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530881 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000882 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530883 log.Fields{
884 "numofTech": tpCount,
885 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
886 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 return nil
888}
889
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700890func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530891 portNo uint32, uplinkClassifier map[string]interface{},
892 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700893 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700894 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530896 log.Fields{
897 "uplinkClassifier": uplinkClassifier,
898 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
900 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530901 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530902}
903
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530905 portNo uint32, downlinkClassifier map[string]interface{},
906 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700907 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700908 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530910 log.Fields{
911 "downlinkClassifier": downlinkClassifier,
912 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
914 if vlan, exists := downlinkClassifier[VlanVid]; exists {
915 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700916 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
918 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530919 log.Fields{
920 "flow": logicalFlow,
921 "device-id": f.deviceHandler.device.Id,
922 "onu-id": onuID,
923 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800924 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400925 }
926 }
927 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530928 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400929
Manikkaraj k884c1242019-04-11 16:26:42 +0530930 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700931 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400932 // vlan_vid is a uint32. must be type asserted as such or conversion fails
933 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530934 if ok {
935 downlinkAction[VlanVid] = dlClVid & 0xfff
936 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530937 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530938 "reason": "failed-to-convert-vlanid-classifier",
939 "vlan-id": VlanVid,
940 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530941 }
942
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700943 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
944 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700947func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530948 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700949 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
950
951 var inverseDirection string
952 if direction == Upstream {
953 inverseDirection = Downstream
954 } else {
955 inverseDirection = Upstream
956 }
957
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530959 log.Fields{
960 "intf-id": intfID,
961 "onu-id": onuID,
962 "uni-id": uniID,
963 "device-id": f.deviceHandler.device.Id,
964 "classifier": classifier,
965 "action": action,
966 "direction": direction,
967 "alloc-id": allocID,
968 "gemport-id": gemPortID,
969 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700970
971 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
974 "device-id": f.deviceHandler.device.Id,
975 "intf-id": intfID,
976 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530978 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800979 classifierProto, err := makeOpenOltClassifierField(classifier)
980 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530981 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530982 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530984 log.Fields{
985 "classifier": *classifierProto,
986 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000987 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800988 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530989 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530990 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000991 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530992 log.Fields{
993 "action": *actionProto,
994 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530996 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800998 log.Fields{
999 "classifier": classifier,
1000 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301001 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001002 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301003 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001004
1005 // Get symmetric flowID if it exists
1006 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1007 // symmetric flow earlier
1008 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1009 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1010 f.subscriberDataPathFlowIDMapLock.RLock()
1011 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1012 f.subscriberDataPathFlowIDMapLock.RUnlock()
1013
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001014 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001015 OnuId: int32(onuID),
1016 UniId: int32(uniID),
1017 FlowId: logicalFlow.Id,
1018 FlowType: direction,
1019 AllocId: int32(allocID),
1020 NetworkIntfId: int32(networkIntfID),
1021 GemportId: int32(gemPortID),
1022 Classifier: classifierProto,
1023 Action: actionProto,
1024 Priority: int32(logicalFlow.Priority),
1025 Cookie: logicalFlow.Cookie,
1026 PortNo: portNo,
1027 TechProfileId: tpID,
1028 ReplicateFlow: len(pbitToGem) > 0,
1029 PbitToGemport: pbitToGem,
1030 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001031 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001032 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001033 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301034 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301036 log.Fields{"direction": direction,
1037 "device-id": f.deviceHandler.device.Id,
1038 "flow": flow,
1039 "intf-id": intfID,
1040 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001041 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1042 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1043 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301044 log.Fields{
1045 "flow": flow,
1046 "device-id": f.deviceHandler.device.Id,
1047 "intf-id": intfID,
1048 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001049 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001050
1051 // Update the current flowID to the map
1052 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1053 f.subscriberDataPathFlowIDMapLock.Lock()
1054 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1055 f.subscriberDataPathFlowIDMapLock.Unlock()
1056
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301058}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001059
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001060func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1061 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001062 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301063
Neha Sharma96b7bf22020-06-15 10:37:32 +00001064 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301065 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301066 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301068 "action": action,
1069 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001070 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301071 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301072
1073 // Clear the action map
1074 for k := range action {
1075 delete(action, k)
1076 }
1077
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001078 action[TrapToHost] = true
1079 classifier[UDPSrc] = uint32(68)
1080 classifier[UDPDst] = uint32(67)
1081 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301082
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001083 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "device-id": f.deviceHandler.device.Id,
1087 "intf-id": intfID,
1088 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301090 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301091
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "ul_classifier": classifier,
1095 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001096 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301097 "intf-id": intfID,
1098 "onu-id": onuID,
1099 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301100
David K. Bainbridge794735f2020-02-11 21:01:37 -08001101 classifierProto, err := makeOpenOltClassifierField(classifier)
1102 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301103 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001106 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301108 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109 }
1110
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001112 OnuId: int32(onuID),
1113 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001114 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001115 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001116 AllocId: int32(allocID),
1117 NetworkIntfId: int32(networkIntfID),
1118 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301119 Classifier: classifierProto,
1120 Action: actionProto,
1121 Priority: int32(logicalFlow.Priority),
1122 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001123 PortNo: portNo,
1124 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125 ReplicateFlow: len(pbitToGem) > 0,
1126 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001127 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001129 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001131 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301132 log.Fields{
1133 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001134 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301135 "intf-id": intfID,
1136 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001137 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1138 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(dhcpFlow.AccessIntfId), dhcpFlow.OnuId, dhcpFlow.UniId, dhcpFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301139 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1140 log.Fields{
1141 "flow": dhcpFlow,
1142 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301143 }
1144
David K. Bainbridge794735f2020-02-11 21:01:37 -08001145 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301146}
1147
Esin Karamanae41e2b2019-12-17 18:13:13 +00001148//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301149func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1151 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001152}
1153
1154//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301155func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001156 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001157
Neha Sharma96b7bf22020-06-15 10:37:32 +00001158 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001159 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301160 return olterrors.NewErrNotFound("nni-interface-id",
1161 log.Fields{
1162 "classifier": classifier,
1163 "action": action,
1164 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001165 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001166 }
1167
1168 // Clear the action map
1169 for k := range action {
1170 delete(action, k)
1171 }
1172
1173 action[TrapToHost] = true
1174 classifier[PacketTagType] = SingleTag
1175 delete(classifier, VlanVid)
1176
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001177 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001180 }
1181
Neha Sharma96b7bf22020-06-15 10:37:32 +00001182 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301183 log.Fields{
1184 "ul_classifier": classifier,
1185 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001186 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301187 "device-id": f.deviceHandler.device.Id,
1188 "intf-id": intfID,
1189 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001190
David K. Bainbridge794735f2020-02-11 21:01:37 -08001191 classifierProto, err := makeOpenOltClassifierField(classifier)
1192 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301193 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001194 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001195 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301196 log.Fields{
1197 "classifier": *classifierProto,
1198 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001199 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301201 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202 }
1203
David K. Bainbridge794735f2020-02-11 21:01:37 -08001204 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001205 OnuId: int32(onuID),
1206 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208 FlowType: Upstream,
1209 AllocId: int32(allocID),
1210 NetworkIntfId: int32(networkIntfID),
1211 GemportId: int32(gemPortID),
1212 Classifier: classifierProto,
1213 Action: actionProto,
1214 Priority: int32(logicalFlow.Priority),
1215 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001216 PortNo: portNo,
1217 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001218 ReplicateFlow: len(pbitToGem) > 0,
1219 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001220 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001223 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001226 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1227 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301228 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 +00001229 }
1230
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232}
1233
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001234// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001235func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1236 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001237 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001238 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301239 log.Fields{
1240 "intf-id": intfID,
1241 "onu-id": onuID,
1242 "port-no": portNo,
1243 "alloc-id": allocID,
1244 "gemport-id": gemPortID,
1245 "vlan-id": vlanID,
1246 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301247
1248 uplinkClassifier := make(map[string]interface{})
1249 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301250
manikkaraj kbf256be2019-03-25 00:13:48 +05301251 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001252 uplinkClassifier[EthType] = uint32(EapEthType)
1253 uplinkClassifier[PacketTagType] = SingleTag
1254 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001255 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301256 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001257 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001258 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001259 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301260 "device-id": f.deviceHandler.device.Id,
1261 "onu-id": onuID,
1262 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301264 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301265 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001266 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301267 log.Fields{
1268 "ul_classifier": uplinkClassifier,
1269 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001270 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301271 "device-id": f.deviceHandler.device.Id,
1272 "intf-id": intfID,
1273 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1276 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301277 return olterrors.NewErrInvalidValue(log.Fields{
1278 "classifier": uplinkClassifier,
1279 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301280 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301282 log.Fields{
1283 "classifier": *classifierProto,
1284 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001285 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301287 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301288 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001289 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301290 log.Fields{
1291 "action": *actionProto,
1292 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001293 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301294 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301295 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001296 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301297 "action": action,
1298 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301300 }
1301
David K. Bainbridge794735f2020-02-11 21:01:37 -08001302 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 OnuId: int32(onuID),
1304 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001305 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001306 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001307 AllocId: int32(allocID),
1308 NetworkIntfId: int32(networkIntfID),
1309 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301310 Classifier: classifierProto,
1311 Action: actionProto,
1312 Priority: int32(logicalFlow.Priority),
1313 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001314 PortNo: portNo,
1315 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 ReplicateFlow: len(pbitToGem) > 0,
1317 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001318 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001319 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301323 log.Fields{
1324 "device-id": f.deviceHandler.device.Id,
1325 "onu-id": onuID,
1326 "intf-id": intfID,
1327 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001328 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1329 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(upstreamFlow.AccessIntfId), upstreamFlow.OnuId, upstreamFlow.UniId, upstreamFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301330 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1331 log.Fields{
1332 "flow": upstreamFlow,
1333 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301334 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301336}
1337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001339 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001340
1341 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1342 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1343 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001344 if vlanID != ReservedVlan {
1345 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001346 classifier.OVid = vid
1347 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001349 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1350 vid := uint32(metadata)
1351 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001352 classifier.IVid = vid
1353 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301355 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001356 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301357 classifier.OPbits = vlanPcp
1358 } else {
1359 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001361 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1362 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1363 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1364 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001365 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001366 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1367 classifier.PktTagType = pktTagType
1368
1369 switch pktTagType {
1370 case SingleTag:
1371 case DoubleTag:
1372 case Untagged:
1373 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001374 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 }
1376 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001377 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301378}
1379
Gamze Abaka724d0852020-03-18 12:10:24 +00001380func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001381 var actionCmd openoltpb2.ActionCmd
1382 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301383 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001384 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301385 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001386 if _, ok := actionInfo[VlanPcp]; ok {
1387 action.Cmd.RemarkInnerPbits = true
1388 action.IPbits = actionInfo[VlanPcp].(uint32)
1389 if _, ok := actionInfo[VlanVid]; ok {
1390 action.Cmd.TranslateInnerTag = true
1391 action.IVid = actionInfo[VlanVid].(uint32)
1392 }
1393 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 } else if _, ok := actionInfo[PushVlan]; ok {
1395 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001397 if _, ok := actionInfo[VlanPcp]; ok {
1398 action.OPbits = actionInfo[VlanPcp].(uint32)
1399 action.Cmd.RemarkOuterPbits = true
1400 if _, ok := classifierInfo[VlanVid]; ok {
1401 action.IVid = classifierInfo[VlanVid].(uint32)
1402 action.Cmd.TranslateInnerTag = true
1403 }
1404 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001405 } else if _, ok := actionInfo[TrapToHost]; ok {
1406 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301407 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001408 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301409 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001410 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301411}
1412
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001413// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001414func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1415 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301416}
1417
Gamze Abakafee36392019-10-03 11:17:24 +00001418// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001419func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301420 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001421 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1422
Gamze Abakafee36392019-10-03 11:17:24 +00001423 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301424 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001425 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301426 // return err
1427 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001428 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001429 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001430 }
1431 return nil
1432}
1433
1434// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301435func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001436 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001437 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001438 }
npujarec5762e2020-01-01 14:08:48 +05301439 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301440 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1441 log.Fields{
1442 "tp-id": tpID,
1443 "uni-port-name": uniPortName,
1444 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001445 }
1446 return nil
1447}
1448
David K. Bainbridge794735f2020-02-11 21:01:37 -08001449func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001450
1451 var intfID uint32
1452 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1453 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1454 */
1455 if deviceFlow.AccessIntfId != -1 {
1456 intfID = uint32(deviceFlow.AccessIntfId)
1457 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001458 // We need to log the valid interface ID.
1459 // For trap-on-nni flows, the access_intf_id is invalid (-1), so choose the network_intf_id.
Daniele Rossi22db98e2019-07-11 11:50:00 +00001460 intfID = uint32(deviceFlow.NetworkIntfId)
1461 }
1462
Neha Sharma96b7bf22020-06-15 10:37:32 +00001463 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301464 "flow": *deviceFlow,
1465 "device-id": f.deviceHandler.device.Id,
1466 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001467 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001468
1469 st, _ := status.FromError(err)
1470 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001471 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001472 "err": err,
1473 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301474 "device-id": f.deviceHandler.device.Id,
1475 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001476 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001478
1479 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001480 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301481 log.Fields{"err": err,
1482 "device-flow": deviceFlow,
1483 "device-id": f.deviceHandler.device.Id,
1484 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001486 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001487 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301488 log.Fields{
1489 "flow": *deviceFlow,
1490 "device-id": f.deviceHandler.device.Id,
1491 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001492
1493 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1494 if deviceFlow.AccessIntfId != -1 {
1495 // No need to register the flow if it is a trap on nni flow.
1496 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1497 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1498 return err
1499 }
1500 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001501 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001502}
1503
Neha Sharma96b7bf22020-06-15 10:37:32 +00001504func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1505 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301506 log.Fields{
1507 "flow": *deviceFlow,
1508 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001509 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001510 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001511 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301513 log.Fields{
1514 "err": err,
1515 "deviceFlow": deviceFlow,
1516 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001517 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001518 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001519 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001520 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001521
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001522 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001523 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001524 "of-flow-id": ofFlowID,
1525 "flow": *deviceFlow,
1526 "device-id": f.deviceHandler.device.Id,
1527 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301529}
1530
David K. Bainbridge794735f2020-02-11 21:01:37 -08001531func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001532
1533 classifierInfo := make(map[string]interface{})
1534 actionInfo := make(map[string]interface{})
1535
1536 classifierInfo[EthType] = uint32(LldpEthType)
1537 classifierInfo[PacketTagType] = Untagged
1538 actionInfo[TrapToHost] = true
1539
1540 // LLDP flow is installed to trap LLDP packets on the NNI port.
1541 // We manage flow_id resource pool on per PON port basis.
1542 // Since this situation is tricky, as a hack, we pass the NNI port
1543 // index (network_intf_id) as PON port Index for the flow_id resource
1544 // pool. Also, there is no ONU Id available for trapping LLDP packets
1545 // on NNI port, use onu_id as -1 (invalid)
1546 // ****************** CAVEAT *******************
1547 // This logic works if the NNI Port Id falls within the same valid
1548 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1549 // we need to have a re-look at this.
1550 // *********************************************
1551
1552 var onuID = -1
1553 var uniID = -1
1554 var gemPortID = -1
1555
Neha Sharma96b7bf22020-06-15 10:37:32 +00001556 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001557 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301558 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001560 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001562 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001563 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001564
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1566 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301567 return olterrors.NewErrInvalidValue(
1568 log.Fields{
1569 "classifier": classifierInfo,
1570 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "classifier": *classifierProto,
1575 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001576 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001577 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301578 return olterrors.NewErrInvalidValue(
1579 log.Fields{
1580 "action": actionInfo,
1581 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001582 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001583 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301584 log.Fields{
1585 "action": *actionProto,
1586 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001587
1588 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1589 OnuId: int32(onuID), // OnuId not required
1590 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001591 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001592 FlowType: Downstream,
1593 NetworkIntfId: int32(networkInterfaceID),
1594 GemportId: int32(gemPortID),
1595 Classifier: classifierProto,
1596 Action: actionProto,
1597 Priority: int32(flow.Priority),
1598 Cookie: flow.Cookie,
1599 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001601 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301602 log.Fields{
1603 "flow": downstreamflow,
1604 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001605 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001606 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301607 log.Fields{
1608 "device-id": f.deviceHandler.device.Id,
1609 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001610 "flow-id": flow.Id})
1611 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1612 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1613 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301614 log.Fields{
1615 "flow": downstreamflow,
1616 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001617 }
1618 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301619}
1620
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001621func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1622 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001623}
1624
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001625//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001627 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1628 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1629 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301631 log.Fields{
1632 "intf-id": intfID,
1633 "onu-id": onuID,
1634 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001636 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301637 return nil, olterrors.NewErrNotFound("onu-child-device",
1638 log.Fields{
1639 "onu-id": onuID,
1640 "intf-id": intfID,
1641 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001642 }
1643 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1644 //better to ad the device to cache here.
1645 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1646 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{
1649 "intf-id": intfID,
1650 "onu-id": onuID,
1651 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001652 }
1653
1654 return onuDev.(*OnuDevice), nil
1655}
1656
1657//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001658func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1659 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "pon-port": intfID,
1662 "onu-id": onuID,
1663 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001664 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001665 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301667 return nil, olterrors.NewErrNotFound("onu",
1668 log.Fields{
1669 "interface-id": parentPortNo,
1670 "onu-id": onuID,
1671 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001672 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301675 log.Fields{
1676 "device-id": f.deviceHandler.device.Id,
1677 "child_device_id": onuDevice.Id,
1678 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301679 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301680}
1681
Neha Sharma96b7bf22020-06-15 10:37:32 +00001682func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1683 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301684 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001685 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301686 log.Fields{
1687 "intf-id": intfID,
1688 "onu-id": onuID,
1689 "uni-id": uniID,
1690 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001691 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301692 }
1693
1694 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "msg": *delGemPortMsg,
1698 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001699 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301700 delGemPortMsg,
1701 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301702 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001703 onuDev.deviceType,
1704 onuDev.deviceID,
1705 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301706 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1707 log.Fields{
1708 "from-adapter": f.deviceHandler.device.Type,
1709 "to-adapter": onuDev.deviceType,
1710 "onu-id": onuDev.deviceID,
1711 "proxyDeviceID": onuDev.proxyDeviceID,
1712 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301713 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "msg": delGemPortMsg,
1717 "from-adapter": f.deviceHandler.device.Type,
1718 "to-adapter": onuDev.deviceType,
1719 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301720 return nil
1721}
1722
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1724 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301725 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301727 log.Fields{
1728 "intf-id": intfID,
1729 "onu-id": onuID,
1730 "uni-id": uniID,
1731 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301733 }
1734
1735 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301737 log.Fields{
1738 "msg": *delTcontMsg,
1739 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001740 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301741 delTcontMsg,
1742 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301743 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001744 onuDev.deviceType,
1745 onuDev.deviceID,
1746 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301747 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1748 log.Fields{
1749 "from-adapter": f.deviceHandler.device.Type,
1750 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1751 "proxyDeviceID": onuDev.proxyDeviceID,
1752 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301755 log.Fields{
1756 "msg": delTcontMsg,
1757 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301758 return nil
1759}
1760
Girish Gowdrac3037402020-01-22 20:29:53 +05301761// Once the gemport is released for a given onu, it also has to be cleared from local cache
1762// which was used for deriving the gemport->logicalPortNo during packet-in.
1763// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1764// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001766
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001767 f.onuGemInfoLock.Lock()
1768 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001769
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301771 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001772 "gem-port-id": gemPortID,
1773 "intf-id": intfID,
1774 "onu-id": onuID,
1775 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001776 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001777
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001778 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001779deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001780 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301781 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001782 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301783 // If the gemport is found, delete it from local cache.
1784 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001785 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1786 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301788 log.Fields{
1789 "intf-id": intfID,
1790 "onu-id": onuID,
1791 "deletedgemport-id": gemPortID,
1792 "gemports": onu.GemPorts,
1793 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001794 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301795 }
1796 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001797 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301798 }
1799 }
1800}
1801
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301802//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001803// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301804func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001805 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001806
Neha Sharma96b7bf22020-06-15 10:37:32 +00001807 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001808 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301809 return olterrors.NewErrNotFound("tp-id",
1810 log.Fields{
1811 "flow": flow,
1812 "intf": Intf,
1813 "onu-id": onuID,
1814 "uni-id": uniID,
1815 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001816 }
Gamze Abakafee36392019-10-03 11:17:24 +00001817
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001818 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1819 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1820 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1821 log.Fields{
1822 "tpPath": tpPath,
1823 "device-id": f.deviceHandler.device.Id})
1824 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1825 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1826 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1827 log.Fields{
1828 "tp-id": tpID,
1829 "path": tpPath}, err)
1830 }
1831
1832 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1833
1834 if used {
1835 f.flowsUsedByGemPortKey.Lock()
1836 defer f.flowsUsedByGemPortKey.Unlock()
1837
1838 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1839 for i, flowIDinMap := range flowIDs {
1840 if flowIDinMap == flowID {
1841 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1842 // everytime flowsUsedByGemPort cache is updated the same should be updated
1843 // in kv store by calling UpdateFlowIDsForGem
1844 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1845 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1846 return err
1847 }
1848 break
1849 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001850 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001851 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1852 log.Fields{
1853 "gemport-id": gemPortID,
1854 "usedByFlows": flowIDs,
1855 "device-id": f.deviceHandler.device.Id})
1856 return nil
1857 }
1858 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1859 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1860 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1861 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1862 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
1863 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
1864 f.onuIdsLock.Lock() // TODO: What is this lock?
1865
1866 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1867 // by calling DeleteFlowIDsForGem
1868 f.flowsUsedByGemPortKey.Lock()
1869 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1870 f.flowsUsedByGemPortKey.Unlock()
1871 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1872 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1873
1874 f.onuIdsLock.Unlock()
1875
1876 // Delete the gem port on the ONU.
1877 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1878 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1879 log.Fields{
1880 "err": err,
1881 "intf": Intf,
1882 "onu-id": onuID,
1883 "uni-id": uniID,
1884 "device-id": f.deviceHandler.device.Id,
1885 "gemport-id": gemPortID})
1886 }
1887 switch techprofileInst := techprofileInst.(type) {
1888 case *tp.TechProfile:
1889 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1890 if !ok {
1891 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1892 logger.Warn(ctx, err)
1893 }
1894 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1895 logger.Warn(ctx, err)
1896 }
1897 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 {
1898 logger.Warn(ctx, err)
1899 }
1900 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 {
1901 logger.Warn(ctx, err)
1902 }
1903 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1904 // Delete the TCONT on the ONU.
1905 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1906 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1907 log.Fields{
1908 "intf": Intf,
1909 "onu-id": onuID,
1910 "uni-id": uniID,
1911 "device-id": f.deviceHandler.device.Id,
1912 "alloc-id": techprofileInst.UsScheduler.AllocID})
1913 }
1914 }
1915 case *tp.EponProfile:
1916 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1917 logger.Warn(ctx, err)
1918 }
1919 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1920 logger.Warn(ctx, err)
1921 }
1922 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1923 // Delete the TCONT on the ONU.
1924 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1925 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301926 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301928 "onu-id": onuID,
1929 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930 "device-id": f.deviceHandler.device.Id,
1931 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001932 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001933 default:
1934 logger.Errorw(ctx, "error-unknown-tech",
1935 log.Fields{
1936 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001937 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001938
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301939 return nil
1940}
1941
David K. Bainbridge794735f2020-02-11 21:01:37 -08001942// nolint: gocyclo
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943func (f *OpenOltFlowMgr) clearFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
1944 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301946 log.Fields{
1947 "flowDirection": flowDirection,
1948 "flow": *flow,
1949 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001950
1951 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001953 }
1954
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301955 classifierInfo := make(map[string]interface{})
1956
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301958 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001959 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001960 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301961 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301962
David K. Bainbridge794735f2020-02-11 21:01:37 -08001963 onuID := int32(onu)
1964 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301965
1966 for _, field := range flows.GetOfbFields(flow) {
1967 if field.Type == flows.IP_PROTO {
1968 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001969 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301970 }
1971 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001972 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301973 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001974 "flow-id": flow.Id,
1975 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301976 "onu-id": onuID,
1977 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301978
1979 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1980 onuID = -1
1981 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001982 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1983 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001984 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001985 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001986 log.Fields{
1987 "port-number": inPort,
1988 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001989 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001990 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
1993 logger.Errorw(ctx, "flow-info-not-found-for-flow-to-be-removed", log.Fields{"flow-id": flow.Id, "intf-id": Intf, "onu-id": onuID, "uni-id": uniID})
1994 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
1995 }
1996 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
1997 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
1998 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1999 return err
2000 }
2001 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2002 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2003 return err
2004 }
2005 if !flowInfo.Flow.ReplicateFlow {
2006 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
2007 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2008 "flow-id": flow.Id,
2009 "stored-flow": flowInfo.Flow,
2010 "device-id": f.deviceHandler.device.Id,
2011 "stored-flow-id": flowInfo.Flow.FlowId,
2012 "onu-id": onuID,
2013 "intf": Intf,
2014 })
2015 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302016 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002017 } else {
2018 gems := make([]uint32, 0)
2019 for _, gem := range flowInfo.Flow.PbitToGemport {
2020 gems = appendUnique32bit(gems, gem)
2021 }
2022 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2023 for _, gem := range gems {
2024 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
2025 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002026 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002028 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002029 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002030 "onu-id": onuID,
2031 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002033 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002034 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302035 }
2036 }
2037 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038
2039 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2040 if isDatapathFlow(flow) {
2041 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2042 var inverseDirection string
2043 if flowDirection == Upstream {
2044 inverseDirection = Downstream
2045 } else {
2046 inverseDirection = Upstream
2047 }
2048
2049 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
2050 delete(f.subscriberDataPathFlowIDMap, keySymm)
2051 }
2052 }
2053 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002054}
2055
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002056//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002057func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002058
2059 f.incrementActiveFlowRemoveCount(ctx, flow)
2060 defer f.decrementActiveFlowRemoveCount(ctx, flow)
2061
Neha Sharma96b7bf22020-06-15 10:37:32 +00002062 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302063 var direction string
2064 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002065
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302066 for _, action := range flows.GetActions(flow) {
2067 if action.Type == flows.OUTPUT {
2068 if out := action.GetOutput(); out != nil {
2069 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002070 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302071 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002072 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002073 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002074 }
2075 }
2076 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002077
2078 if flows.HasGroup(flow) {
2079 direction = Multicast
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002080 return f.clearFlowFromResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002081 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302082 direction = Upstream
2083 } else {
2084 direction = Downstream
2085 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302086
Neha Sharma96b7bf22020-06-15 10:37:32 +00002087 _, intfID, onuID, uniID, _, _, err := FlowExtractInfo(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002088 if err != nil {
2089 return err
2090 }
2091
2092 userKey := tpLockKey{intfID, onuID, uniID}
2093
2094 // Serialize flow removes on a per subscriber basis
2095 if f.perUserFlowHandleLock.TryLock(userKey) {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002096 err = f.clearFlowFromResourceManager(ctx, flow, direction) //TODO: Take care of the limitations
Girish Gowdracefae192020-03-19 18:14:10 -07002097 f.perUserFlowHandleLock.Unlock(userKey)
2098 } else {
2099 // Ideally this should never happen
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100 logger.Errorw(ctx, "failed-to-acquire-lock-to-remove-flow--remove-aborted", log.Fields{"flow": flow})
Girish Gowdracefae192020-03-19 18:14:10 -07002101 return errors.New("failed-to-acquire-per-user-lock")
2102 }
2103
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002104 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002105}
2106
Esin Karamanae41e2b2019-12-17 18:13:13 +00002107//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2108func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2109 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2110 if ethType, ok := classifierInfo[EthType]; ok {
2111 if ethType.(uint32) == IPv4EthType {
2112 if ipProto, ok := classifierInfo[IPProto]; ok {
2113 if ipProto.(uint32) == IgmpProto {
2114 return true
2115 }
2116 }
2117 }
2118 }
2119 }
2120 return false
2121}
2122
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002123// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302124// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002125func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002126 classifierInfo := make(map[string]interface{})
2127 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002128 var UsMeterID uint32
2129 var DsMeterID uint32
2130
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302132 log.Fields{
2133 "flow": flow,
2134 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002135 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002136
Neha Sharma96b7bf22020-06-15 10:37:32 +00002137 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002138 if err != nil {
2139 // Error logging is already done in the called function
2140 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002141 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302142 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002143
Esin Karamanccb714b2019-11-29 15:02:06 +00002144 if flows.HasGroup(flow) {
2145 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002146 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002147 }
2148
manikkaraj k17652a72019-05-06 09:06:36 -04002149 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002151 if err != nil {
2152 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002153 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002154 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002155
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302157 log.Fields{
2158 "classifierinfo_inport": classifierInfo[InPort],
2159 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002160 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002161
Humera Kouser94d7a842019-08-25 19:04:32 -04002162 if ethType, ok := classifierInfo[EthType]; ok {
2163 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002165 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002166 }
2167 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002168 if ipProto, ok := classifierInfo[IPProto]; ok {
2169 if ipProto.(uint32) == IPProtoDhcp {
2170 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302171 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002173 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002174 }
2175 }
2176 }
2177 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002178 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002180 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002181 }
A R Karthick1f85b802019-10-11 05:06:05 +00002182
Girish Gowdra9602eb42020-09-09 15:50:39 -07002183 // If we are here it is not a trap-from-nni flow, i.e., it is subscriber specific flow.
2184 // Wait for any FlowRemoves for that specific subscriber to finish first
2185 // The goal here is to serialize FlowRemove and FlowAdd. FlowRemove take priority
2186 f.waitForFlowRemoveToFinish(ctx, flow)
2187
npujarec5762e2020-01-01 14:08:48 +05302188 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002189
Neha Sharma96b7bf22020-06-15 10:37:32 +00002190 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002191 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302192 return olterrors.NewErrNotFound("tpid-for-flow",
2193 log.Fields{
2194 "flow": flow,
2195 "intf-id": IntfID,
2196 "onu-id": onuID,
2197 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002198 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002199 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302200 log.Fields{
2201 "tp-id": TpID,
2202 "intf-id": intfID,
2203 "onu-id": onuID,
2204 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002205 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002206 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002207 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002208 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002209 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002210 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002211
2212 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002213 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002214}
Girish Gowdra3d633032019-12-10 16:37:05 +05302215
Girish Gowdra9602eb42020-09-09 15:50:39 -07002216//WaitForFlowRemoveToFinishForSubscriber blocks until flow removes are complete for a given subscriber
2217func (f *OpenOltFlowMgr) WaitForFlowRemoveToFinishForSubscriber(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) {
2218 var flowRemoveData pendingFlowRemoveData
2219 var ok bool
2220
2221 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
2222 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2223
2224 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
2225 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
2226 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
2227 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2228 return
Girish Gowdra3d633032019-12-10 16:37:05 +05302229 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07002230 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
2231
2232 // Wait for all flow removes to finish first
2233 <-flowRemoveData.allFlowsRemoved
2234
2235 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 -07002236}
2237
Esin Karamanccb714b2019-11-29 15:02:06 +00002238// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002239func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002240 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002241 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302242 "classifier-info": classifierInfo,
2243 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002244
Esin Karaman65409d82020-03-18 10:58:18 +00002245 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002246 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002247 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002248 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002249
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002250 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002251
David K. Bainbridge794735f2020-02-11 21:01:37 -08002252 onuID := NoneOnuID
2253 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002255 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002256 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002257 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002258 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2260 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002261 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002262 }
2263 groupID := actionInfo[GroupID].(uint32)
2264 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002265 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002266 FlowType: Multicast,
2267 NetworkIntfId: int32(networkInterfaceID),
2268 GroupId: groupID,
2269 Classifier: classifierProto,
2270 Priority: int32(flow.Priority),
2271 Cookie: flow.Cookie}
2272
Kent Hagermane6ff1012020-07-14 15:07:53 -04002273 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002274 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002275 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002276 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002277 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002278 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002279 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002280 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002281 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002282 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002283 //cached group can be removed now
2284 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2285 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2286 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002287 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002288
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002289 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2290 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2291 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002292 }
2293 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002294}
2295
Esin Karaman65409d82020-03-18 10:58:18 +00002296//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2297func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2298 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002299 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002300 if err != nil {
2301 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2302 }
2303 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002304 }
Esin Karaman65409d82020-03-18 10:58:18 +00002305 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302306 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002307 if e == nil && len(nniPorts) > 0 {
2308 return nniPorts[0], nil
2309 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302310 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002311}
2312
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002313//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002315
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302317 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302319 log.Fields{
2320 "intf-id": intfID,
2321 "onu-id": onuID,
2322 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002323 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302324 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002326
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002328 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002330 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002331 tpDownloadMsg,
2332 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302333 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002334 onuDev.deviceType,
2335 onuDev.deviceID,
2336 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002337 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302338 return olterrors.NewErrCommunication("send-techprofile-download-request",
2339 log.Fields{
2340 "from-adapter": f.deviceHandler.device.Type,
2341 "to-adapter": onuDev.deviceType,
2342 "onu-id": onuDev.deviceID,
2343 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002344 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302346 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302347}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002348
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302349//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002350func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302351
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002352 f.onuGemInfoLock.Lock()
2353 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002354 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002355 // If the ONU already exists in onuGemInfo list, nothing to do
2356 for _, onu := range onugem {
2357 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2358 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2359 log.Fields{"onuID": onuID,
2360 "serialNum": serialNum})
2361 return nil
2362 }
2363 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002364
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302365 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002366 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002367 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002368 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302369 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002370 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302371 log.Fields{
2372 "intf-id": intfID,
2373 "onu-id": onuID,
2374 "serial-num": serialNum,
2375 "onu": onu,
2376 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002377 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002378}
2379
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302380//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302381func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002382
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002383 f.onuGemInfoLock.Lock()
2384 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002385
Neha Sharma96b7bf22020-06-15 10:37:32 +00002386 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302387 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002388 "gem-port-id": gemPort,
2389 "intf-id": intfID,
2390 "onu-id": onuID,
2391 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002392 "onu-gem": f.onuGemInfo})
2393 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302394 // update the gem to the local cache as well as to kv strore
2395 for idx, onu := range onugem {
2396 if onu.OnuID == onuID {
2397 // check if gem already exists , else update the cache and kvstore
2398 for _, gem := range onu.GemPorts {
2399 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302401 log.Fields{
2402 "gem": gemPort,
2403 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302404 return
2405 }
2406 }
2407 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002408 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002409 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302410 }
2411 }
npujarec5762e2020-01-01 14:08:48 +05302412 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302413 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002414 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302415 log.Fields{
2416 "intf-id": intfID,
2417 "onu-id": onuID,
2418 "gemPort": gemPort,
2419 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002420 return
2421 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302423 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002424 "gem-port-id": gemPort,
2425 "intf-id": intfID,
2426 "onu-id": onuID,
2427 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002428 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002429}
2430
2431// This function Lookup maps by serialNumber or (intfId, gemPort)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002432
2433//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 +00002434func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302435
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002436 f.onuGemInfoLock.RLock()
2437 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302438
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002439 logger.Debugw(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302440 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002441 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002442 "onu-geminfo": f.onuGemInfo,
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002443 "intf-id": intfID,
2444 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302445 // get onuid from the onugem info cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002446 onugem := f.onuGemInfo
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002447
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302448 for _, onu := range onugem {
2449 for _, gem := range onu.GemPorts {
2450 if gem == gemPortID {
2451 return onu.OnuID, nil
2452 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002453 }
2454 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002455 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2456 "gem-port-id": gemPortID,
2457 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002458 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002459 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302460 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002461 "interface-id": intfID,
2462 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002463 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002464}
2465
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002466//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302467func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002468 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002469 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002470 var err error
2471
2472 if packetIn.IntfType == "pon" {
2473 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002475 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002476 return logicalPortNum, err
2477 }
2478 if packetIn.PortNo != 0 {
2479 logicalPortNum = packetIn.PortNo
2480 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002481 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002483 }
2484 // 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 +00002485 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002486 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002487 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05302490 log.Fields{
2491 "logical-port-num": logicalPortNum,
2492 "intf-type": packetIn.IntfType,
2493 "packet": hex.EncodeToString(packetIn.Pkt),
2494 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002495 return logicalPortNum, nil
2496}
2497
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002498//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002499func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002500 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002501
2502 ctag, priority, err := getCTagFromPacket(ctx, packet)
2503 if err != nil {
2504 return 0, err
2505 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302506
Esin Karaman7fb80c22020-07-16 14:23:33 +00002507 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002508 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002509 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002510 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002511 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302512 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002513 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302514 log.Fields{
2515 "pktinkey": pktInkey,
2516 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002517
2518 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002519 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302520 //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 +00002521 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302522 if err == nil {
2523 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002524 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302525 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002526 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002527 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302528 log.Fields{
2529 "pktinkey": pktInkey,
2530 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302531 return gemPortID, nil
2532 }
2533 }
Shrey Baid26912972020-04-16 21:02:31 +05302534 return uint32(0), olterrors.NewErrNotFound("gem-port",
2535 log.Fields{
2536 "pktinkey": pktInkey,
2537 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002538
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002539}
2540
David K. Bainbridge794735f2020-02-11 21:01:37 -08002541func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002542 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002544 classifier[PacketTagType] = DoubleTag
2545 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 /* We manage flowId resource pool on per PON port basis.
2547 Since this situation is tricky, as a hack, we pass the NNI port
2548 index (network_intf_id) as PON port Index for the flowId resource
2549 pool. Also, there is no ONU Id available for trapping DHCP packets
2550 on NNI port, use onu_id as -1 (invalid)
2551 ****************** CAVEAT *******************
2552 This logic works if the NNI Port Id falls within the same valid
2553 range of PON Port Ids. If this doesn't work for some OLT Vendor
2554 we need to have a re-look at this.
2555 *********************************************
2556 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002557 onuID := -1
2558 uniID := -1
2559 gemPortID := -1
2560 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002561 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302562 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302563 return olterrors.NewErrNotFound("nni-intreface-id",
2564 log.Fields{
2565 "classifier": classifier,
2566 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002567 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302568 }
2569
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002570 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002571 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002572 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002573 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002574
David K. Bainbridge794735f2020-02-11 21:01:37 -08002575 classifierProto, err := makeOpenOltClassifierField(classifier)
2576 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002577 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002578 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002579 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002580 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002581 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002582 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002583 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002584 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002585 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2586 OnuId: int32(onuID), // OnuId not required
2587 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002588 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002589 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002590 AllocId: int32(allocID), // AllocId not used
2591 NetworkIntfId: int32(networkInterfaceID),
2592 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593 Classifier: classifierProto,
2594 Action: actionProto,
2595 Priority: int32(logicalFlow.Priority),
2596 Cookie: logicalFlow.Cookie,
2597 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002598 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002599 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002600 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002601 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002602 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2603 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2604 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002605 }
2606 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002607}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002608
Esin Karamanae41e2b2019-12-17 18:13:13 +00002609//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2610func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2611 var packetType string
2612 ovid, ivid := false, false
2613 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2614 vid := vlanID & VlanvIDMask
2615 if vid != ReservedVlan {
2616 ovid = true
2617 }
2618 }
2619 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2620 vid := uint32(metadata)
2621 if vid != ReservedVlan {
2622 ivid = true
2623 }
2624 }
2625 if ovid && ivid {
2626 packetType = DoubleTag
2627 } else if !ovid && !ivid {
2628 packetType = Untagged
2629 } else {
2630 packetType = SingleTag
2631 }
2632 return packetType
2633}
2634
2635//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002636func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002638 action := make(map[string]interface{})
2639 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2640 action[TrapToHost] = true
2641 /* We manage flowId resource pool on per PON port basis.
2642 Since this situation is tricky, as a hack, we pass the NNI port
2643 index (network_intf_id) as PON port Index for the flowId resource
2644 pool. Also, there is no ONU Id available for trapping packets
2645 on NNI port, use onu_id as -1 (invalid)
2646 ****************** CAVEAT *******************
2647 This logic works if the NNI Port Id falls within the same valid
2648 range of PON Port Ids. If this doesn't work for some OLT Vendor
2649 we need to have a re-look at this.
2650 *********************************************
2651 */
2652 onuID := -1
2653 uniID := -1
2654 gemPortID := -1
2655 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002656 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002657 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302658 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002659 "classifier": classifier,
2660 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002661 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002662 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002664 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002665 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002666 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002667
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 classifierProto, err := makeOpenOltClassifierField(classifier)
2669 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002670 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002671 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002672 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002673 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002674 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002675 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002677 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002678 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2679 OnuId: int32(onuID), // OnuId not required
2680 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002681 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002682 FlowType: Downstream,
2683 AllocId: int32(allocID), // AllocId not used
2684 NetworkIntfId: int32(networkInterfaceID),
2685 GemportId: int32(gemPortID), // GemportId not used
2686 Classifier: classifierProto,
2687 Action: actionProto,
2688 Priority: int32(logicalFlow.Priority),
2689 Cookie: logicalFlow.Cookie,
2690 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002691 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002692 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002694 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002695 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2696 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2697 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002698 }
2699 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002700}
2701
salmansiddiqui7ac62132019-08-22 03:58:50 +00002702func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2703 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302704 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002705 }
2706 if Dir == tp_pb.Direction_UPSTREAM {
2707 return "upstream", nil
2708 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2709 return "downstream", nil
2710 }
2711 return "", nil
2712}
2713
Kent Hagermane6ff1012020-07-14 15:07:53 -04002714// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302715func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002716 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002717 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002718 var gemPort uint32
2719 intfID := args[IntfID]
2720 onuID := args[OnuID]
2721 uniID := args[UniID]
2722 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002723 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002724 pbitToGem := make(map[uint32]uint32)
2725
2726 if len(gemPorts) == 1 {
2727 // If there is only single gemport use that and do not populate pbitToGem map
2728 gemPort = gemPorts[0]
2729 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2730 for idx, gemID := range gemPorts {
2731 switch TpInst := TpInst.(type) {
2732 case *tp.TechProfile:
2733 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2734 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2735 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2736 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2737 // this pcp bit traffic.
2738 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2739 if pbitSet == pbit1 {
2740 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2741 pbitToGem[pcp] = gemID
2742 }
2743 }
2744 default:
2745 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2746 return
2747 }
2748 }
2749 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2750 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2751 tp_pb.Direction_UPSTREAM,
2752 pcp.(uint32))
2753 }
2754
salmansiddiqui7ac62132019-08-22 03:58:50 +00002755 if ipProto, ok := classifierInfo[IPProto]; ok {
2756 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002757 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002758 "tp-id": tpID,
2759 "alloc-id": allocID,
2760 "intf-id": intfID,
2761 "onu-id": onuID,
2762 "uni-id": uniID,
2763 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002764 //Adding DHCP upstream flow
2765 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2766 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002767 }
2768
Girish Gowdra32625212020-04-29 11:26:35 -07002769 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302771 log.Fields{
2772 "intf-id": intfID,
2773 "onu-id": onuID,
2774 "uni-id": uniID,
2775 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2777 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002778 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002779 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002780 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781 return
2782 }
2783 } else if ethType, ok := classifierInfo[EthType]; ok {
2784 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002786 "intf-id": intfID,
2787 "onu-id": onuID,
2788 "uni-id": uniID,
2789 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002790 var vlanID uint32
2791 if val, ok := classifierInfo[VlanVid]; ok {
2792 vlanID = (val.(uint32)) & VlanvIDMask
2793 } else {
2794 vlanID = DefaultMgmtVlan
2795 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002796 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2797 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002798 }
2799 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002800 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002801 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002802 "intf-id": intfID,
2803 "onu-id": onuID,
2804 "uni-id": uniID,
2805 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002806 //Adding HSIA upstream flow
2807 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2808 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002809 }
2810 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002811 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002812 "intf-id": intfID,
2813 "onu-id": onuID,
2814 "uni-id": uniID,
2815 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002816 //Adding HSIA downstream flow
2817 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2818 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819 }
2820 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002821 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302822 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002823 "intf-id": intfID,
2824 "onu-id": onuID,
2825 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302826 "classifier": classifierInfo,
2827 "action": actionInfo,
2828 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002829 return
2830 }
2831 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002832 go func() {
2833 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2834 logger.Warn(ctx, err)
2835 }
2836 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002837}
2838
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002839func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2840 f.flowsUsedByGemPortKey.RLock()
2841 flowIDList := f.flowsUsedByGemPort[gemPortID]
2842 f.flowsUsedByGemPortKey.RUnlock()
2843 return len(flowIDList) > 1
2844
Gamze Abakafee36392019-10-03 11:17:24 +00002845}
2846
npujarec5762e2020-01-01 14:08:48 +05302847func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2848 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002849 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2850 for _, currentGemPort := range currentGemPorts {
2851 for _, tpGemPort := range tpGemPorts {
2852 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2853 return true, currentGemPort
2854 }
2855 }
2856 }
Girish Gowdra54934262019-11-13 14:19:55 +05302857 if tpInst.InstanceCtrl.Onu == "single-instance" {
2858 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002859 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002860 logger.Warn(ctx, err)
2861 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002862 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002863 logger.Warn(ctx, err)
2864 }
Girish Gowdra54934262019-11-13 14:19:55 +05302865
2866 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2867 // still be used on other uni ports.
2868 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2869 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002870 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002871 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302872 for i := 0; i < len(tpInstances); i++ {
2873 tpI := tpInstances[i]
2874 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302875 for _, tpGemPort := range tpGemPorts {
2876 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002877 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302878 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302879 }
2880 }
2881 }
2882 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002883 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002884 return false, 0
2885}
2886
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002888 for _, field := range flows.GetOfbFields(flow) {
2889 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002890 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002891 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002892 } else if field.Type == flows.ETH_DST {
2893 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002895 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002896 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002898 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002899 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002901 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302902 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002903 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002904 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002907 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002910 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002911 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002913 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002916 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002919 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002920 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002921 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002922 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002923 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002926 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002927 return
2928 }
2929 }
2930}
2931
Neha Sharma96b7bf22020-06-15 10:37:32 +00002932func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002933 for _, action := range flows.GetActions(flow) {
2934 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002935 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002936 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002937 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002939 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002940 }
Scott Baker355d1742019-10-24 10:57:52 -07002941 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002944 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 if out := action.GetPush(); out != nil {
2946 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002947 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 } else {
2949 actionInfo[PushVlan] = true
2950 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002951 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302952 log.Fields{
2953 "push-tpid": actionInfo[TPID].(uint32),
2954 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 }
2956 }
Scott Baker355d1742019-10-24 10:57:52 -07002957 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 if out := action.GetSetField(); out != nil {
2959 if field := out.GetField(); field != nil {
2960 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002961 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002962 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2964 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
2966 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002967 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002970 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 }
2972 }
2973 return nil
2974}
2975
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002977 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002978 fieldtype := ofbField.GetType()
2979 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002980 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2981 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002983 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002985 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002986 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2987 pcp := ofbField.GetVlanPcp()
2988 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002989 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002990 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002992 }
2993 }
2994}
2995
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002997 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002999 } else {
3000 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003002 }
3003}
3004
Neha Sharma96b7bf22020-06-15 10:37:32 +00003005func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003006 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003008 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3009 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003010 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003012 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303013 log.Fields{
3014 "newinport": classifierInfo[InPort].(uint32),
3015 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003016 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303017 return olterrors.NewErrNotFound("child-in-port",
3018 log.Fields{
3019 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3020 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 }
3022 }
3023 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003025 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003026 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003027 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003028 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303030 log.Fields{
3031 "newoutport": actionInfo[Output].(uint32),
3032 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303034 return olterrors.NewErrNotFound("out-port",
3035 log.Fields{
3036 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3037 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038 }
3039 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3040 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003041 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303044 log.Fields{
3045 "newinport": actionInfo[Output].(uint32),
3046 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303048 return olterrors.NewErrNotFound("nni-port",
3049 log.Fields{
3050 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3051 "in-port": classifierInfo[InPort].(uint32),
3052 "out-port": actionInfo[Output].(uint32),
3053 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 }
3055 }
3056 }
3057 return nil
3058}
Gamze Abakafee36392019-10-03 11:17:24 +00003059
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003061 /* Metadata 8 bytes:
3062 Most Significant 2 Bytes = Inner VLAN
3063 Next 2 Bytes = Tech Profile ID(TPID)
3064 Least Significant 4 Bytes = Port ID
3065 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3066 subscriber related flows.
3067 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003069 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003070 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003071 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003073 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003074}
3075
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003076func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3077 for _, sliceElement := range slice {
3078 if sliceElement == item {
3079 return slice
3080 }
3081 }
3082 return append(slice, item)
3083}
3084
3085func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003086 for _, sliceElement := range slice {
3087 if sliceElement == item {
3088 return slice
3089 }
3090 }
3091 return append(slice, item)
3092}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303093
3094// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003095func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303096
3097 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3098 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003100 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003102 log.Fields{
3103 "port-number": action[Output].(uint32),
3104 "error": err})
3105 return uint32(0), err
3106 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003107 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303108 return intfID, nil
3109 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003110 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003111 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003113 log.Fields{
3114 "port-number": action[Output].(uint32),
3115 "error": err})
3116 return uint32(0), err
3117 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303119 return intfID, nil
3120 }
3121 return uint32(0), nil
3122}
3123
3124// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003125func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3126 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3127 if err != nil {
3128 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3129 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3130 return
3131 }
3132 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003133
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003134 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003135 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003136 f.packetInGemPortLock.RUnlock()
3137
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303138 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003139 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 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 +05303141 log.Fields{
3142 "pktinkey": pktInkey,
3143 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003144 return
3145 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303146 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003147 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003148 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003149 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003150
npujarec5762e2020-01-01 14:08:48 +05303151 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003152 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 +05303153 log.Fields{
3154 "pktinkey": pktInkey,
3155 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303156}
3157
Esin Karaman7fb80c22020-07-16 14:23:33 +00003158//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3159func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3160 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003161 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003162 return 0, 0, errors.New("invalid packet length")
3163 }
3164 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3165 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3166
3167 var index int8
3168 if outerEthType == 0x8100 {
3169 if innerEthType == 0x8100 {
3170 // q-in-q 802.1ad or 802.1q double tagged packet.
3171 // get the inner vlanId
3172 index = 18
3173 } else {
3174 index = 14
3175 }
3176 priority := (packet[index] >> 5) & 0x7
3177 //13 bits composes vlanId value
3178 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3179 return vlan, priority, nil
3180 }
3181 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3182 return 0, 0, nil
3183}
3184
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303185// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303186func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003187
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003188 f.onuGemInfoLock.Lock()
3189 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003190
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003191 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303192 for idx, onu := range onugem {
3193 if onu.OnuID == onuID {
3194 for _, uni := range onu.UniPorts {
3195 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196 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 +05303197 return
3198 }
3199 }
3200 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003201 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303202 }
3203 }
npujarec5762e2020-01-01 14:08:48 +05303204 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003205
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303206}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303207
npujarec5762e2020-01-01 14:08:48 +05303208func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3209 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303210 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303212 return
3213 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003214 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303215 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003216 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303217 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003218 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303219}
Esin Karamanccb714b2019-11-29 15:02:06 +00003220
Girish Gowdra9602eb42020-09-09 15:50:39 -07003221//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3222// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003223func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003224 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003225 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003226 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3227 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3228
Esin Karamanccb714b2019-11-29 15:02:06 +00003229 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003230 logger.Warnw(ctx, "no-inport-found--cannot-release-resources-of-the-multicast-flow", log.Fields{"flowId:": flow.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003231 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003232 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003233
3234 var onuID = int32(NoneOnuID)
3235 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003236 var flowID uint64
3237 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3238 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3239 log.Fields{
3240 "flow": flow,
3241 "device-id": f.deviceHandler.device.Id,
3242 "intf-id": networkInterfaceID,
3243 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003244 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003245 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3246 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3247 log.Fields{
3248 "flow": flowInfo.Flow,
3249 "flow-id": flow.Id,
3250 "device-id": f.deviceHandler.device.Id})
3251 // Remove from device
3252 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3253 // DKB
3254 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3255 log.Fields{
3256 "flow-id": flow.Id,
3257 "error": err})
3258 return err
3259 }
3260 // Remove flow from KV store
3261 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00003262}
3263
Girish Gowdra9602eb42020-09-09 15:50:39 -07003264func (f *OpenOltFlowMgr) incrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003265
3266 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3267 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3268
Girish Gowdra9602eb42020-09-09 15:50:39 -07003269 inPort, outPort := getPorts(flow)
3270 logger.Debugw(ctx, "increment-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3271 if inPort != InvalidPort && outPort != InvalidPort {
3272 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3273 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3274 logger.Debugw(ctx, "increment-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3275
Girish Gowdra9602eb42020-09-09 15:50:39 -07003276 flowRemoveData, ok := f.pendingFlowRemoveDataPerSubscriber[key]
3277 if !ok {
3278 flowRemoveData = pendingFlowRemoveData{
3279 pendingFlowRemoveCount: 0,
3280 allFlowsRemoved: make(chan struct{}),
3281 }
3282 }
3283 flowRemoveData.pendingFlowRemoveCount++
3284 f.pendingFlowRemoveDataPerSubscriber[key] = flowRemoveData
3285
3286 logger.Debugw(ctx, "current-flow-remove-count–increment",
3287 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3288 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
Esin Karamanccb714b2019-11-29 15:02:06 +00003289 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003290}
3291
Girish Gowdra9602eb42020-09-09 15:50:39 -07003292func (f *OpenOltFlowMgr) decrementActiveFlowRemoveCount(ctx context.Context, flow *ofp.OfpFlowStats) {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003293 f.pendingFlowRemoveDataPerSubscriberLock.Lock()
3294 defer f.pendingFlowRemoveDataPerSubscriberLock.Unlock()
3295
Girish Gowdra9602eb42020-09-09 15:50:39 -07003296 inPort, outPort := getPorts(flow)
3297 logger.Debugw(ctx, "decrement-flow-remove-count-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3298 if inPort != InvalidPort && outPort != InvalidPort {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003299 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
Girish Gowdra9602eb42020-09-09 15:50:39 -07003300 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3301 logger.Debugw(ctx, "decrement-flow-remove-count-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3302
Girish Gowdra9602eb42020-09-09 15:50:39 -07003303 if val, ok := f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3304 logger.Fatalf(ctx, "flow-remove-key-not-found", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3305 } else {
3306 if val.pendingFlowRemoveCount > 0 {
3307 val.pendingFlowRemoveCount--
3308 }
3309 logger.Debugw(ctx, "current-flow-remove-count-after-decrement",
3310 log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID,
3311 "currCnt": f.pendingFlowRemoveDataPerSubscriber[key].pendingFlowRemoveCount})
3312 // If all flow removes have finished, then close the channel to signal the receiver
3313 // to go ahead with flow adds.
3314 if val.pendingFlowRemoveCount == 0 {
3315 close(val.allFlowsRemoved)
3316 delete(f.pendingFlowRemoveDataPerSubscriber, key)
3317 return
3318 }
3319 f.pendingFlowRemoveDataPerSubscriber[key] = val
Esin Karaman0ebd2a32020-02-09 18:45:36 +00003320 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003321 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003322}
3323
3324func (f *OpenOltFlowMgr) waitForFlowRemoveToFinish(ctx context.Context, flow *ofp.OfpFlowStats) {
3325 var flowRemoveData pendingFlowRemoveData
3326 var ok bool
3327 inPort, outPort := getPorts(flow)
3328 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-inPort-out-port", log.Fields{"inPort": inPort, "out-port": outPort})
3329 if inPort != InvalidPort && outPort != InvalidPort {
3330 _, intfID, onuID, uniID := ExtractAccessFromFlow(inPort, outPort)
3331 key := pendingFlowRemoveDataKey{intfID: intfID, onuID: onuID, uniID: uniID}
3332 logger.Debugw(ctx, "wait-for-flow-remove-to-finish-for-subscriber", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3333
3334 f.pendingFlowRemoveDataPerSubscriberLock.RLock()
3335 if flowRemoveData, ok = f.pendingFlowRemoveDataPerSubscriber[key]; !ok {
3336 logger.Debugw(ctx, "no-pending-flow-to-remove", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3337 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3338 return
3339 }
3340 f.pendingFlowRemoveDataPerSubscriberLock.RUnlock()
3341
3342 // Wait for all flow removes to finish first
3343 <-flowRemoveData.allFlowsRemoved
3344
3345 logger.Debugw(ctx, "all-flows-cleared--handling-flow-add-now", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID})
3346 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003347}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003348
3349// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3350func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3351 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3352 if err != nil {
3353 _ = olterrors.NewErrNotFound("onu", log.Fields{
3354 "pon-port": f.ponPortIdx}, err).Log()
3355 return
3356 }
3357
3358 f.subscriberDataPathFlowIDMapLock.Lock()
3359 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3360
3361 for _, onu := range onuGemInfo {
3362 for _, uniID := range onu.UniPorts {
3363 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3364 if err != nil {
3365 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3366 }
3367 for _, flowID := range flowIDs {
3368 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3369 if flowInfo == nil {
3370 // Error is already logged in the called function
3371 continue
3372 }
3373 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3374 flowInfo.Flow.FlowType == Downstream &&
3375 flowInfo.Flow.Classifier.OVid > 0 &&
3376 flowInfo.Flow.TechProfileId > 0 {
3377 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3378 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3379 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3380 }
3381 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3382 flowInfo.Flow.FlowType == Upstream &&
3383 flowInfo.Flow.Action.OVid > 0 &&
3384 flowInfo.Flow.TechProfileId > 0 {
3385 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3386 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3387 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3388 }
3389 }
3390 }
3391 }
3392 }
3393}
3394
3395// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3396func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3397 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3398}