blob: a9e2431ec06bb35344ba7c16d5967ca670279be6 [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"
serkant.uluderya4aff1862020-09-17 23:35:26 +030025 "strings"
26 "sync"
27
Girish Gowdraa09aeab2020-09-14 16:30:52 -070028 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
29 "github.com/opencord/voltha-lib-go/v4/pkg/log"
30 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070032 "github.com/opencord/voltha-protos/v4/go/common"
33 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
34 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
35 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
36 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
37 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040038
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
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030057 //PPPoEDEthType PPPoE discovery ethernet type value
58 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070059
Andrea Campanella7acc0b92020-02-14 09:20:49 +010060 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
61 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040062
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070063 //DefaultMgmtVlan default vlan value
64 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053065
manikkaraj kbf256be2019-03-25 00:13:48 +053066 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070067
David K. Bainbridge82efc492019-09-04 09:57:11 -070068 //Upstream constant
69 Upstream = "upstream"
70 //Downstream constant
71 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000072 //Multicast constant
73 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070074 //PacketTagType constant
75 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070076 //Untagged constant
77 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070078 //SingleTag constant
79 SingleTag = "single_tag"
80 //DoubleTag constant
81 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053082
83 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084
85 //EthType constant
86 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000087 //EthDst constant
88 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089 //TPID constant
90 TPID = "tpid"
91 //IPProto constant
92 IPProto = "ip_proto"
93 //InPort constant
94 InPort = "in_port"
95 //VlanVid constant
96 VlanVid = "vlan_vid"
97 //VlanPcp constant
98 VlanPcp = "vlan_pcp"
99
100 //UDPDst constant
101 UDPDst = "udp_dst"
102 //UDPSrc constant
103 UDPSrc = "udp_src"
104 //Ipv4Dst constant
105 Ipv4Dst = "ipv4_dst"
106 //Ipv4Src constant
107 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700108 //Metadata constant
109 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 //TunnelID constant
111 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700112 //Output constant
113 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000114 //GroupID constant
115 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700116 // Actions
117
118 //PopVlan constant
119 PopVlan = "pop_vlan"
120 //PushVlan constant
121 PushVlan = "push_vlan"
122 //TrapToHost constant
123 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400124 //MaxMeterBand constant
125 MaxMeterBand = 2
126 //VlanPCPMask contant
127 VlanPCPMask = 0xFF
128 //VlanvIDMask constant
129 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000130 //IntfID constant
131 IntfID = "intfId"
132 //OnuID constant
133 OnuID = "onuId"
134 //UniID constant
135 UniID = "uniId"
136 //PortNo constant
137 PortNo = "portNo"
138 //AllocID constant
139 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000140 //GemID constant
141 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000142
143 //NoneOnuID constant
144 NoneOnuID = -1
145 //NoneUniID constant
146 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700147
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700148 // Max number of flows that can be queued per ONU
149 maxConcurrentFlowsPerOnu = 20
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
Esin Karamandf392e12020-12-16 13:33:09 +0000155type gemPortKey struct {
156 intfID uint32
157 gemPort uint32
158}
159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
169 flowMetadata *voltha.FlowMetadata
170}
171
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700172// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
173type subscriberDataPathFlowIDKey struct {
174 intfID uint32
175 onuID uint32
176 uniID uint32
177 direction string
178 tpID uint32
179}
180
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700181// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
182// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
183// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
184// flow and processes it serially
185type flowControlBlock struct {
186 ctx context.Context // Flow handler context
187 addFlow bool // if true flow to be added, else removed
188 flow *voltha.OfpFlowStats // Flow message
189 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
190 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000191}
192
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700193//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530194type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700195 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
196 techprofile map[uint32]tp.TechProfileIf
197 deviceHandler *DeviceHandler
198 grpMgr *OpenOltGroupMgr
199 resourceMgr *rsrcMgr.OpenOltResourceMgr
200
201 onuIdsLock sync.RWMutex // TODO: Do we need this?
202
203 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
204 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
205
206 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
207 packetInGemPortLock sync.RWMutex
208
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700209 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700210 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700211 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700212 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700213
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700214 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
215 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
216 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
217 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700218
219 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
220 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
221 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000222
223 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
224 gemToUniMap map[gemPortKey][]uint32
225 //We need to have a global lock on the gemToUniLock map
226 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530227}
228
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700229//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000231 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233 var err error
234 var idx uint32
235
manikkaraj kbf256be2019-03-25 00:13:48 +0530236 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700237 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530238 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000239 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000240 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
241 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 return nil
243 }
William Kurkian740a09c2019-10-23 17:07:38 -0400244 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700245 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530246 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700247 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700248 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700249 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
250 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251
252 // Create a slice of buffered channels for handling concurrent flows per ONU.
253 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
254 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
255 for i := range flowMgr.incomingFlows {
256 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
257 // Spin up a go routine to handling incoming flows (add/remove).
258 // There will be on go routine per ONU.
259 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
260 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
261 }
262
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
265 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530266 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700267 //Load flowID list per gem map per interface from the kvstore.
268 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000269 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000270
271 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
272 flowMgr.gemToUniLock = sync.RWMutex{}
273
Girish Gowdra9602eb42020-09-09 15:50:39 -0700274 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530277 return &flowMgr
278}
279
Esin Karamandf392e12020-12-16 13:33:09 +0000280// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
281func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
282 f.gemToUniLock.Lock()
283 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
284 f.gemToUniLock.Unlock()
285}
286
287// fromGemToUniMap returns onu and uni ID associated with the given key
288func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
289 f.gemToUniLock.RLock()
290 defer f.gemToUniLock.RUnlock()
291 val, ok := f.gemToUniMap[key]
292 return val, ok
293}
294
295// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
296func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
297 f.gemToUniLock.Lock()
298 defer f.gemToUniLock.Unlock()
299 delete(f.gemToUniMap, key)
300}
301
Kent Hagermane6ff1012020-07-14 15:07:53 -0400302func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700303 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
304 // Flow is not replicated in this case, we need to register the flow for a single gem-port
305 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
306 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
307 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
308 for _, gemPort := range deviceFlow.PbitToGemport {
309 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
310 return err
311 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700312 }
Gamze Abakafee36392019-10-03 11:17:24 +0000313 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700314 return nil
315}
316
317func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
318 f.flowsUsedByGemPortKey.Lock()
319 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
320 if !ok {
321 flowIDList = []uint64{flowFromCore.Id}
322 }
323 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
324 f.flowsUsedByGemPort[gemPortID] = flowIDList
325 f.flowsUsedByGemPortKey.Unlock()
326
327 // update the flowids for a gem to the KVstore
328 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400329}
330
Girish Gowdra9602eb42020-09-09 15:50:39 -0700331func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000332 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200333 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000334 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530335 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700336 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530337
Neha Sharma96b7bf22020-06-15 10:37:32 +0000338 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530339 "device-id": f.deviceHandler.device.Id,
340 "intf-id": intfID,
341 "onu-id": onuID,
342 "uni-id": uniID,
343 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700344 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530345 "action": actionInfo,
346 "usmeter-iD": UsMeterID,
347 "dsmeter-iD": DsMeterID,
348 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400349 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
350 // is because the flow is an NNI flow and there would be no onu resources associated with it
351 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400352 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200353 cause := "no-onu-id-for-flow"
354 fields := log.Fields{
355 "onu": onuID,
356 "port-no": portNo,
357 "classifer": classifierInfo,
358 "action": actionInfo,
359 "device-id": f.deviceHandler.device.Id}
360 logger.Errorw(ctx, cause, fields)
361 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530362 }
363
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700364 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000365 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530366 "uni": uni,
367 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530368
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700369 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
370 "device-id": f.deviceHandler.device.Id,
371 "intf-id": intfID,
372 "onu-id": onuID,
373 "uni-id": uniID,
374 "port-no": portNo,
375 "classifier": classifierInfo,
376 "action": actionInfo,
377 "usmeter-id": UsMeterID,
378 "dsmeter-id": DsMeterID,
379 "tp-id": TpID})
380 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
381 if allocID == 0 || gemPorts == nil || TpInst == nil {
382 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
383 return olterrors.NewErrNotFound(
384 "alloc-id-gem-ports-tp-unavailable",
385 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700387 args := make(map[string]uint32)
388 args[IntfID] = intfID
389 args[OnuID] = onuID
390 args[UniID] = uniID
391 args[PortNo] = portNo
392 args[AllocID] = allocID
393
394 /* Flows can be added specific to gemport if p-bits are received.
395 * If no pbit mentioned then adding flows for all gemports
396 */
397 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
398
Andrea Campanellabfe08432020-09-11 17:07:03 +0200399 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530400}
401
salmansiddiqui7ac62132019-08-22 03:58:50 +0000402// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530403func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400404
Neha Sharma96b7bf22020-06-15 10:37:32 +0000405 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530406 log.Fields{"dir": sq.direction,
407 "intf-id": sq.intfID,
408 "onu-id": sq.onuID,
409 "uni-id": sq.uniID,
410 "tp-id": sq.tpID,
411 "meter-id": sq.meterID,
412 "tp-inst": sq.tpInst,
413 "flowmetadata": sq.flowMetadata,
414 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415
Gamze Abakafee36392019-10-03 11:17:24 +0000416 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000417 if err != nil {
418 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400419 }
420
421 /* Lets make a simple assumption that if the meter-id is present on the KV store,
422 * then the scheduler and queues configuration is applied on the OLT device
423 * in the given direction.
424 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000425
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530427 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530429 return olterrors.NewErrNotFound("meter",
430 log.Fields{"intf-id": sq.intfID,
431 "onu-id": sq.onuID,
432 "uni-id": sq.uniID,
433 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000435
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000437 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000438 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400439 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530441 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800442 "unsupported": "meter-id",
443 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530444 "meter-id-in-flow": sq.meterID,
445 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400446 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447
Neha Sharma96b7bf22020-06-15 10:37:32 +0000448 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530449 log.Fields{
450 "meter-id": sq.meterID,
451 "direction": Direction,
452 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000453
Gamze Abakafee36392019-10-03 11:17:24 +0000454 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000456 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000457 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000459
460 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530461 return olterrors.NewErrNotFound("scheduler-config",
462 log.Fields{
463 "intf-id": sq.intfID,
464 "direction": sq.direction,
465 "tp-inst": sq.tpInst,
466 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000467 }
468
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000470 if sq.flowMetadata != nil {
471 for _, meter := range sq.flowMetadata.Meters {
472 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400473 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530475 log.Fields{"meterConfig": meterConfig,
476 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400477 break
478 }
479 }
480 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000481 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482 }
483 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530484 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800485 "reason": "Could-not-get-meterbands-from-flowMetadata",
486 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530487 "meter-id": sq.meterID,
488 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530491 log.Fields{"Bands": meterConfig.Bands,
492 "meter-id": sq.meterID,
493 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530494 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800495 "reason": "Invalid-number-of-bands-in-meter",
496 "meterband-count": len(meterConfig.Bands),
497 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530498 "meter-id": sq.meterID,
499 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 }
501 cir := meterConfig.Bands[0].Rate
502 cbs := meterConfig.Bands[0].BurstSize
503 eir := meterConfig.Bands[1].Rate
504 ebs := meterConfig.Bands[1].BurstSize
505 pir := cir + eir
506 pbs := cbs + ebs
507 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
508
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700509 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000510 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400511
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700512 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530513 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
514 log.Fields{"intf-id": sq.intfID,
515 "direction": sq.direction,
516 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400517 }
518
salmansiddiqui7ac62132019-08-22 03:58:50 +0000519 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400520 * store the meter id on the KV store, for further reference.
521 */
npujarec5762e2020-01-01 14:08:48 +0530522 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 +0530523 return olterrors.NewErrAdapter("failed-updating-meter-id",
524 log.Fields{"onu-id": sq.onuID,
525 "meter-id": sq.meterID,
526 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000528 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530529 log.Fields{"direction": Direction,
530 "Meter": meterConfig,
531 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400532 return nil
533}
534
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700535func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000536 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537
538 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530539 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
540 log.Fields{"intf-id": sq.intfID,
541 "direction": sq.direction,
542 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000543 }
544
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530546 log.Fields{
547 "direction": sq.direction,
548 "TrafficScheds": TrafficSched,
549 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530550 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551 IntfId: sq.intfID, OnuId: sq.onuID,
552 UniId: sq.uniID, PortNo: sq.uniPort,
553 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000554 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000555 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000556 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530557 "direction": sq.direction,
558 "traffic-queues": trafficQueues,
559 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000560
561 // On receiving the CreateTrafficQueues request, the driver should create corresponding
562 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000563 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530564 log.Fields{"direction": sq.direction,
565 "traffic-queues": trafficQueues,
566 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530567 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000568 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
569 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000570 TrafficQueues: trafficQueues,
571 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530572 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000573 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530575 "direction": sq.direction,
576 "traffic-queues": trafficQueues,
577 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000578
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700582 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 //assumed that there is only one queue per PON for the multicast service
584 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
585 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000587 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700588 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 gemPortID: multicastQueuePerPonPort.GemportId,
590 servicePriority: multicastQueuePerPonPort.Priority,
591 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700592 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000593 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400594 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
595 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
596 return err
597 }
Shrey Baid26912972020-04-16 21:02:31 +0530598
Neha Sharma96b7bf22020-06-15 10:37:32 +0000599 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000600 }
601 }
602 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000603 return nil
604}
605
salmansiddiqui7ac62132019-08-22 03:58:50 +0000606// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530607func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400608
609 var Direction string
610 var SchedCfg *tp_pb.SchedulerConfig
611 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000612 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530613 log.Fields{
614 "direction": sq.direction,
615 "intf-id": sq.intfID,
616 "onu-id": sq.onuID,
617 "uni-id": sq.uniID,
618 "uni-port": sq.uniPort,
619 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000620 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400622 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000623 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000624 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400625 Direction = "downstream"
626 }
627
Girish Kumar8f73fe02019-12-09 13:19:37 +0000628 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530629 return olterrors.NewErrNotFound("scheduler-config",
630 log.Fields{
631 "int-id": sq.intfID,
632 "direction": sq.direction,
633 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000634 }
635
npujarec5762e2020-01-01 14:08:48 +0530636 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400637 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530638 return olterrors.NewErrNotFound("meter",
639 log.Fields{
640 "onu-id": sq.onuID,
641 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400642 }
643 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000644 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530645 log.Fields{
646 "direction": Direction,
647 "intf-id": sq.intfID,
648 "onu-id": sq.onuID,
649 "uni-id": sq.uniID,
650 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400651 return nil
652 }
653 cir := KVStoreMeter.Bands[0].Rate
654 cbs := KVStoreMeter.Bands[0].BurstSize
655 eir := KVStoreMeter.Bands[1].Rate
656 ebs := KVStoreMeter.Bands[1].BurstSize
657 pir := cir + eir
658 pbs := cbs + ebs
659
660 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
661
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700662 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664
Neha Sharma96b7bf22020-06-15 10:37:32 +0000665 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000666 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530667 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
668 log.Fields{
669 "intf-id": sq.intfID,
670 "direction": sq.direction,
671 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000672 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400673
npujarec5762e2020-01-01 14:08:48 +0530674 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000675 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
676 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000677 TrafficQueues: TrafficQueues,
678 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000679 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530680 log.Fields{
681 "intf-id": sq.intfID,
682 "traffic-queues": TrafficQueues,
683 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000685 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530686 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000687 IntfId: sq.intfID, OnuId: sq.onuID,
688 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000690 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530691 log.Fields{
692 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700693 "traffic-schedulers": TrafficSched,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400697 }
698
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700699 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
700 log.Fields{"device-id": f.deviceHandler.device.Id,
701 "intf-id": sq.intfID,
702 "onu-id": sq.onuID,
703 "uni-id": sq.uniID,
704 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000705
706 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400707 * delete the meter id on the KV store.
708 */
npujarec5762e2020-01-01 14:08:48 +0530709 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400710 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530711 return olterrors.NewErrAdapter("unable-to-remove-meter",
712 log.Fields{
713 "onu": sq.onuID,
714 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700715 "device-id": f.deviceHandler.device.Id,
716 "intf-id": sq.intfID,
717 "onu-id": sq.onuID,
718 "uni-id": sq.uniID,
719 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400720 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530722 log.Fields{
723 "meter-id": KVStoreMeter.MeterId,
724 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700725 "device-id": f.deviceHandler.device.Id,
726 "intf-id": sq.intfID,
727 "onu-id": sq.onuID,
728 "uni-id": sq.uniID,
729 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400730 return err
731}
732
Gamze Abakafee36392019-10-03 11:17:24 +0000733// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700734func (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 +0000735 var allocIDs []uint32
736 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530737 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530738 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000739 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000740
npujarec5762e2020-01-01 14:08:48 +0530741 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
742 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530744
Neha Sharma96b7bf22020-06-15 10:37:32 +0000745 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530746 "intf-id": intfID,
747 "onu-id": onuID,
748 "uni-id": uniID,
749 "device-id": f.deviceHandler.device.Id,
750 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530751
Manikkaraj kb1d51442019-07-23 10:41:02 -0400752 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530753 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000754 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000755 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530756 log.Fields{
757 "path": tpPath,
758 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530759 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000760 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530761 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000762 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530763 log.Fields{
764 "error": err,
765 "tp-id": TpID,
766 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000767 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530768 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400769 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
770 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
771 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530772 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000773 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530774 log.Fields{
775 "uni": uni,
776 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530777 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530778 }
Gamze Abakafee36392019-10-03 11:17:24 +0000779
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700780 switch tpInst := techProfileInstance.(type) {
781 case *tp.TechProfile:
782 if UsMeterID != 0 {
783 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
784 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
785 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000786 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700787 log.Fields{
788 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700789 "onu-id": onuID,
790 "uni-id": uniID,
791 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700792 "meter-id": UsMeterID,
793 "device-id": f.deviceHandler.device.Id})
794 return 0, nil, nil
795 }
796 }
797 if DsMeterID != 0 {
798 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
799 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
800 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700802 log.Fields{
803 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700804 "onu-id": onuID,
805 "uni-id": uniID,
806 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700807 "meter-id": DsMeterID,
808 "device-id": f.deviceHandler.device.Id})
809 return 0, nil, nil
810 }
811 }
812 allocID := tpInst.UsScheduler.AllocID
813 for _, gem := range tpInst.UpstreamGemPortAttributeList {
814 gemPortIDs = append(gemPortIDs, gem.GemportID)
815 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700816 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000817
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700818 if tpInstanceExists {
819 return allocID, gemPortIDs, techProfileInstance
820 }
821
822 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700823 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700824 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700826 log.Fields{
827 "alloc-ids": allocIDs,
828 "gemports": allgemPortIDs,
829 "device-id": f.deviceHandler.device.Id})
830 // Send Tconts and GEM ports to KV store
831 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530832 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700833 case *tp.EponProfile:
834 // CreateSchedulerQueues for EPON needs to be implemented here
835 // when voltha-protos for EPON is completed.
836 allocID := tpInst.AllocID
837 for _, gem := range tpInst.UpstreamQueueAttributeList {
838 gemPortIDs = append(gemPortIDs, gem.GemportID)
839 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700840 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841
842 if tpInstanceExists {
843 return allocID, gemPortIDs, techProfileInstance
844 }
845
846 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700847 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700848 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 log.Fields{
851 "alloc-ids": allocIDs,
852 "gemports": allgemPortIDs,
853 "device-id": f.deviceHandler.device.Id})
854 // Send Tconts and GEM ports to KV store
855 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
856 return allocID, gemPortIDs, techProfileInstance
857 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000858 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700859 log.Fields{
860 "tpInst": tpInst})
861 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530862 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530863}
864
npujarec5762e2020-01-01 14:08:48 +0530865func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530866
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530868 log.Fields{
869 "intf-id": intfID,
870 "onu-id": onuID,
871 "uni-id": uniID,
872 "alloc-id": allocID,
873 "gemport-ids": gemPortIDs,
874 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530876 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 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 +0530878 }
npujarec5762e2020-01-01 14:08:48 +0530879 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000880 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 +0530881 }
npujarec5762e2020-01-01 14:08:48 +0530882 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000883 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamandf392e12020-12-16 13:33:09 +0000884 } else {
885 //add to gem to uni cache
886 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530887 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888 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 -0400889 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530890 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400891 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530892}
893
Esin Karamandf392e12020-12-16 13:33:09 +0000894//addGemPortUniAssociationsToCache
895func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
896 for _, gemPortID := range gemPortIDs {
897 key := gemPortKey{
898 intfID: intfID,
899 gemPort: gemPortID,
900 }
901 f.toGemToUniMap(ctx, key, onuID, uniID)
902 }
903 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
904 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
905}
906
Neha Sharma96b7bf22020-06-15 10:37:32 +0000907func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000908 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530909 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000910 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700911 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400912 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000913 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530914 log.Fields{
915 "intf-id": intfID,
916 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530917 }
918 }
919 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400920 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530921 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530922 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800923 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530924 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
925 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530926 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000927 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530928 log.Fields{
929 "numofTech": tpCount,
930 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
931 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530932 return nil
933}
934
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700935func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530936 portNo uint32, uplinkClassifier map[string]interface{},
937 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700938 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700939 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000940 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530941 log.Fields{
942 "uplinkClassifier": uplinkClassifier,
943 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700944 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
945 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530946 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530947}
948
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700949func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530950 portNo uint32, downlinkClassifier map[string]interface{},
951 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700952 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700953 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000954 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530955 log.Fields{
956 "downlinkClassifier": downlinkClassifier,
957 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400958 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
959 if vlan, exists := downlinkClassifier[VlanVid]; exists {
960 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700961 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000962 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
963 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530964 log.Fields{
965 "flow": logicalFlow,
966 "device-id": f.deviceHandler.device.Id,
967 "onu-id": onuID,
968 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800969 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400970 }
971 }
972 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400974
Manikkaraj k884c1242019-04-11 16:26:42 +0530975 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700976 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400977 // vlan_vid is a uint32. must be type asserted as such or conversion fails
978 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530979 if ok {
980 downlinkAction[VlanVid] = dlClVid & 0xfff
981 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530982 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530983 "reason": "failed-to-convert-vlanid-classifier",
984 "vlan-id": VlanVid,
985 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530986 }
987
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700988 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
989 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530990}
991
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700992func (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 +0530993 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700994 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
995
996 var inverseDirection string
997 if direction == Upstream {
998 inverseDirection = Downstream
999 } else {
1000 inverseDirection = Upstream
1001 }
1002
Neha Sharma96b7bf22020-06-15 10:37:32 +00001003 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301004 log.Fields{
1005 "intf-id": intfID,
1006 "onu-id": onuID,
1007 "uni-id": uniID,
1008 "device-id": f.deviceHandler.device.Id,
1009 "classifier": classifier,
1010 "action": action,
1011 "direction": direction,
1012 "alloc-id": allocID,
1013 "gemport-id": gemPortID,
1014 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001015
1016 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001017 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301018 log.Fields{
1019 "device-id": f.deviceHandler.device.Id,
1020 "intf-id": intfID,
1021 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301023 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001024 classifierProto, err := makeOpenOltClassifierField(classifier)
1025 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301026 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301027 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001028 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301029 log.Fields{
1030 "classifier": *classifierProto,
1031 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001032 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001033 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301034 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301035 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301037 log.Fields{
1038 "action": *actionProto,
1039 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301041 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301042 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 log.Fields{
1044 "classifier": classifier,
1045 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301046 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001047 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301048 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001049
1050 // Get symmetric flowID if it exists
1051 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1052 // symmetric flow earlier
1053 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1054 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1055 f.subscriberDataPathFlowIDMapLock.RLock()
1056 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1057 f.subscriberDataPathFlowIDMapLock.RUnlock()
1058
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001059 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001060 OnuId: int32(onuID),
1061 UniId: int32(uniID),
1062 FlowId: logicalFlow.Id,
1063 FlowType: direction,
1064 AllocId: int32(allocID),
1065 NetworkIntfId: int32(networkIntfID),
1066 GemportId: int32(gemPortID),
1067 Classifier: classifierProto,
1068 Action: actionProto,
1069 Priority: int32(logicalFlow.Priority),
1070 Cookie: logicalFlow.Cookie,
1071 PortNo: portNo,
1072 TechProfileId: tpID,
1073 ReplicateFlow: len(pbitToGem) > 0,
1074 PbitToGemport: pbitToGem,
1075 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001076 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001078 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301079 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301081 log.Fields{"direction": direction,
1082 "device-id": f.deviceHandler.device.Id,
1083 "flow": flow,
1084 "intf-id": intfID,
1085 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001086 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1087 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1088 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301089 log.Fields{
1090 "flow": flow,
1091 "device-id": f.deviceHandler.device.Id,
1092 "intf-id": intfID,
1093 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001094 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001095
1096 // Update the current flowID to the map
1097 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1098 f.subscriberDataPathFlowIDMapLock.Lock()
1099 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1100 f.subscriberDataPathFlowIDMapLock.Unlock()
1101
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301103}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001104
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001105func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1106 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001107 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301108
Neha Sharma96b7bf22020-06-15 10:37:32 +00001109 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301110 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301111 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001112 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301113 "action": action,
1114 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301116 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301117
1118 // Clear the action map
1119 for k := range action {
1120 delete(action, k)
1121 }
1122
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001123 action[TrapToHost] = true
1124 classifier[UDPSrc] = uint32(68)
1125 classifier[UDPDst] = uint32(67)
1126 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301127
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001128 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001129 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301130 log.Fields{
1131 "device-id": f.deviceHandler.device.Id,
1132 "intf-id": intfID,
1133 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001134 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301135 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301136
Neha Sharma96b7bf22020-06-15 10:37:32 +00001137 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301138 log.Fields{
1139 "ul_classifier": classifier,
1140 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001141 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301142 "intf-id": intfID,
1143 "onu-id": onuID,
1144 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 classifierProto, err := makeOpenOltClassifierField(classifier)
1147 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301148 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301149 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001150 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001151 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001152 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301153 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301154 }
1155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001157 OnuId: int32(onuID),
1158 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001159 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001160 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001161 AllocId: int32(allocID),
1162 NetworkIntfId: int32(networkIntfID),
1163 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301164 Classifier: classifierProto,
1165 Action: actionProto,
1166 Priority: int32(logicalFlow.Priority),
1167 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001168 PortNo: portNo,
1169 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001170 ReplicateFlow: len(pbitToGem) > 0,
1171 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001172 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001174 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001176 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301177 log.Fields{
1178 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001179 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301180 "intf-id": intfID,
1181 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001182 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1183 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 +05301184 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1185 log.Fields{
1186 "flow": dhcpFlow,
1187 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 }
1189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301191}
1192
Esin Karamanae41e2b2019-12-17 18:13:13 +00001193//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301194func (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 -07001195 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1196 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197}
1198
1199//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301200func (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 -07001201 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 +00001202
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001204 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301205 return olterrors.NewErrNotFound("nni-interface-id",
1206 log.Fields{
1207 "classifier": classifier,
1208 "action": action,
1209 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001211 }
1212
1213 // Clear the action map
1214 for k := range action {
1215 delete(action, k)
1216 }
1217
1218 action[TrapToHost] = true
1219 classifier[PacketTagType] = SingleTag
1220 delete(classifier, VlanVid)
1221
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001222 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001223 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225 }
1226
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301228 log.Fields{
1229 "ul_classifier": classifier,
1230 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001231 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301232 "device-id": f.deviceHandler.device.Id,
1233 "intf-id": intfID,
1234 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235
David K. Bainbridge794735f2020-02-11 21:01:37 -08001236 classifierProto, err := makeOpenOltClassifierField(classifier)
1237 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301238 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001239 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301241 log.Fields{
1242 "classifier": *classifierProto,
1243 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001244 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001247 }
1248
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001250 OnuId: int32(onuID),
1251 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001252 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253 FlowType: Upstream,
1254 AllocId: int32(allocID),
1255 NetworkIntfId: int32(networkIntfID),
1256 GemportId: int32(gemPortID),
1257 Classifier: classifierProto,
1258 Action: actionProto,
1259 Priority: int32(logicalFlow.Priority),
1260 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001261 PortNo: portNo,
1262 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001263 ReplicateFlow: len(pbitToGem) > 0,
1264 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001265 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266
David K. Bainbridge794735f2020-02-11 21:01:37 -08001267 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001268 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 -08001269 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001271 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1272 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 +05301273 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 +00001274 }
1275
David K. Bainbridge794735f2020-02-11 21:01:37 -08001276 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277}
1278
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001279// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
1280func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001281 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001282 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32, ethType uint32) error {
1283 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301284 log.Fields{
1285 "intf-id": intfID,
1286 "onu-id": onuID,
1287 "port-no": portNo,
1288 "alloc-id": allocID,
1289 "gemport-id": gemPortID,
1290 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001291 "flow": logicalFlow,
1292 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301293
1294 uplinkClassifier := make(map[string]interface{})
1295 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301296
manikkaraj kbf256be2019-03-25 00:13:48 +05301297 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001298 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001299 uplinkClassifier[PacketTagType] = SingleTag
1300 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001301 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301302 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001303 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001304 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001305 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301306 "device-id": f.deviceHandler.device.Id,
1307 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001308 "intf-id": intfID,
1309 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301311 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001312 //Add Uplink EthType Flow
1313 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301314 log.Fields{
1315 "ul_classifier": uplinkClassifier,
1316 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001317 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301318 "device-id": f.deviceHandler.device.Id,
1319 "intf-id": intfID,
1320 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301321
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1323 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301324 return olterrors.NewErrInvalidValue(log.Fields{
1325 "classifier": uplinkClassifier,
1326 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301327 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001328 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301329 log.Fields{
1330 "classifier": *classifierProto,
1331 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001332 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001333 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301334 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301335 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001336 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301337 log.Fields{
1338 "action": *actionProto,
1339 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001340 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301341 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301342 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301344 "action": action,
1345 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001346 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301347 }
1348
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 OnuId: int32(onuID),
1351 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001352 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001353 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001354 AllocId: int32(allocID),
1355 NetworkIntfId: int32(networkIntfID),
1356 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301357 Classifier: classifierProto,
1358 Action: actionProto,
1359 Priority: int32(logicalFlow.Priority),
1360 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001361 PortNo: portNo,
1362 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001363 ReplicateFlow: len(pbitToGem) > 0,
1364 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001367 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001369 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301370 log.Fields{
1371 "device-id": f.deviceHandler.device.Id,
1372 "onu-id": onuID,
1373 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001374 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301375 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001376 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1377 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 +05301378 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1379 log.Fields{
1380 "flow": upstreamFlow,
1381 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301384}
1385
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001387 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001388
1389 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1390 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1391 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001392 if vlanID != ReservedVlan {
1393 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001394 classifier.OVid = vid
1395 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001397 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1398 vid := uint32(metadata)
1399 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001400 classifier.IVid = vid
1401 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301402 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301403 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001404 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301405 classifier.OPbits = vlanPcp
1406 } else {
1407 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301408 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001409 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1410 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1411 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1412 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001413 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1415 classifier.PktTagType = pktTagType
1416
1417 switch pktTagType {
1418 case SingleTag:
1419 case DoubleTag:
1420 case Untagged:
1421 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001422 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301423 }
1424 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
Gamze Abaka724d0852020-03-18 12:10:24 +00001428func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var actionCmd openoltpb2.ActionCmd
1430 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301431 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001432 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301433 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001434 if _, ok := actionInfo[VlanPcp]; ok {
1435 action.Cmd.RemarkInnerPbits = true
1436 action.IPbits = actionInfo[VlanPcp].(uint32)
1437 if _, ok := actionInfo[VlanVid]; ok {
1438 action.Cmd.TranslateInnerTag = true
1439 action.IVid = actionInfo[VlanVid].(uint32)
1440 }
1441 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001442 } else if _, ok := actionInfo[PushVlan]; ok {
1443 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001445 if _, ok := actionInfo[VlanPcp]; ok {
1446 action.OPbits = actionInfo[VlanPcp].(uint32)
1447 action.Cmd.RemarkOuterPbits = true
1448 if _, ok := classifierInfo[VlanVid]; ok {
1449 action.IVid = classifierInfo[VlanVid].(uint32)
1450 action.Cmd.TranslateInnerTag = true
1451 }
1452 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001453 } else if _, ok := actionInfo[TrapToHost]; ok {
1454 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001456 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001458 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301459}
1460
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001461// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001462func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1463 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301464}
1465
Gamze Abakafee36392019-10-03 11:17:24 +00001466// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001467func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301468 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001469 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1470
Gamze Abakafee36392019-10-03 11:17:24 +00001471 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301472 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001473 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301474 // return err
1475 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001476 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001477 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001478 }
1479 return nil
1480}
1481
1482// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301483func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001484 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001485 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001486 }
npujarec5762e2020-01-01 14:08:48 +05301487 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301488 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1489 log.Fields{
1490 "tp-id": tpID,
1491 "uni-port-name": uniPortName,
1492 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001493 }
1494 return nil
1495}
1496
David K. Bainbridge794735f2020-02-11 21:01:37 -08001497func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001498
1499 var intfID uint32
1500 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1501 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1502 */
1503 if deviceFlow.AccessIntfId != -1 {
1504 intfID = uint32(deviceFlow.AccessIntfId)
1505 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001506 // We need to log the valid interface ID.
1507 // 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 +00001508 intfID = uint32(deviceFlow.NetworkIntfId)
1509 }
1510
Neha Sharma96b7bf22020-06-15 10:37:32 +00001511 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301512 "flow": *deviceFlow,
1513 "device-id": f.deviceHandler.device.Id,
1514 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001515 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001516
1517 st, _ := status.FromError(err)
1518 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001519 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001520 "err": err,
1521 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301522 "device-id": f.deviceHandler.device.Id,
1523 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001524 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301525 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001526
1527 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301529 log.Fields{"err": err,
1530 "device-flow": deviceFlow,
1531 "device-id": f.deviceHandler.device.Id,
1532 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001533 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001535 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301536 log.Fields{
1537 "flow": *deviceFlow,
1538 "device-id": f.deviceHandler.device.Id,
1539 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001540
1541 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1542 if deviceFlow.AccessIntfId != -1 {
1543 // No need to register the flow if it is a trap on nni flow.
1544 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1545 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1546 return err
1547 }
1548 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001549 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001550}
1551
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1553 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301554 log.Fields{
1555 "flow": *deviceFlow,
1556 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001557 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001558 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001559 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301561 log.Fields{
1562 "err": err,
1563 "deviceFlow": deviceFlow,
1564 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001565 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001567 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001568 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001569
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001572 "of-flow-id": ofFlowID,
1573 "flow": *deviceFlow,
1574 "device-id": f.deviceHandler.device.Id,
1575 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001576 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301577}
1578
David K. Bainbridge794735f2020-02-11 21:01:37 -08001579func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001580
1581 classifierInfo := make(map[string]interface{})
1582 actionInfo := make(map[string]interface{})
1583
1584 classifierInfo[EthType] = uint32(LldpEthType)
1585 classifierInfo[PacketTagType] = Untagged
1586 actionInfo[TrapToHost] = true
1587
1588 // LLDP flow is installed to trap LLDP packets on the NNI port.
1589 // We manage flow_id resource pool on per PON port basis.
1590 // Since this situation is tricky, as a hack, we pass the NNI port
1591 // index (network_intf_id) as PON port Index for the flow_id resource
1592 // pool. Also, there is no ONU Id available for trapping LLDP packets
1593 // on NNI port, use onu_id as -1 (invalid)
1594 // ****************** CAVEAT *******************
1595 // This logic works if the NNI Port Id falls within the same valid
1596 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1597 // we need to have a re-look at this.
1598 // *********************************************
1599
1600 var onuID = -1
1601 var uniID = -1
1602 var gemPortID = -1
1603
Neha Sharma96b7bf22020-06-15 10:37:32 +00001604 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301606 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001608 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001609 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001611 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001612
David K. Bainbridge794735f2020-02-11 21:01:37 -08001613 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1614 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301615 return olterrors.NewErrInvalidValue(
1616 log.Fields{
1617 "classifier": classifierInfo,
1618 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001619 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001620 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301621 log.Fields{
1622 "classifier": *classifierProto,
1623 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001624 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301626 return olterrors.NewErrInvalidValue(
1627 log.Fields{
1628 "action": actionInfo,
1629 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001630 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301632 log.Fields{
1633 "action": *actionProto,
1634 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001635
1636 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1637 OnuId: int32(onuID), // OnuId not required
1638 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001639 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001640 FlowType: Downstream,
1641 NetworkIntfId: int32(networkInterfaceID),
1642 GemportId: int32(gemPortID),
1643 Classifier: classifierProto,
1644 Action: actionProto,
1645 Priority: int32(flow.Priority),
1646 Cookie: flow.Cookie,
1647 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001649 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301650 log.Fields{
1651 "flow": downstreamflow,
1652 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001653 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301655 log.Fields{
1656 "device-id": f.deviceHandler.device.Id,
1657 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001658 "flow-id": flow.Id})
1659 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1660 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1661 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{
1663 "flow": downstreamflow,
1664 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 }
1666 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301667}
1668
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001669func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1670 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001671}
1672
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001673//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001675 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1676 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1677 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301679 log.Fields{
1680 "intf-id": intfID,
1681 "onu-id": onuID,
1682 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001684 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301685 return nil, olterrors.NewErrNotFound("onu-child-device",
1686 log.Fields{
1687 "onu-id": onuID,
1688 "intf-id": intfID,
1689 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001690 }
1691 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1692 //better to ad the device to cache here.
1693 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1694 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "intf-id": intfID,
1698 "onu-id": onuID,
1699 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001700 }
1701
1702 return onuDev.(*OnuDevice), nil
1703}
1704
1705//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001706func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1707 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301708 log.Fields{
1709 "pon-port": intfID,
1710 "onu-id": onuID,
1711 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001712 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001713 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001714 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301715 return nil, olterrors.NewErrNotFound("onu",
1716 log.Fields{
1717 "interface-id": parentPortNo,
1718 "onu-id": onuID,
1719 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001720 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301721 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001722 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301723 log.Fields{
1724 "device-id": f.deviceHandler.device.Id,
1725 "child_device_id": onuDevice.Id,
1726 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301727 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301728}
1729
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1731 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301732 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001733 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301734 log.Fields{
1735 "intf-id": intfID,
1736 "onu-id": onuID,
1737 "uni-id": uniID,
1738 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001739 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301740 }
1741
1742 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001743 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301744 log.Fields{
1745 "msg": *delGemPortMsg,
1746 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001747 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301748 delGemPortMsg,
1749 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001750 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001751 onuDev.deviceType,
1752 onuDev.deviceID,
1753 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301754 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1755 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001756 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301757 "to-adapter": onuDev.deviceType,
1758 "onu-id": onuDev.deviceID,
1759 "proxyDeviceID": onuDev.proxyDeviceID,
1760 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "msg": delGemPortMsg,
1765 "from-adapter": f.deviceHandler.device.Type,
1766 "to-adapter": onuDev.deviceType,
1767 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301768 return nil
1769}
1770
Neha Sharma96b7bf22020-06-15 10:37:32 +00001771func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1772 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301773 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301775 log.Fields{
1776 "intf-id": intfID,
1777 "onu-id": onuID,
1778 "uni-id": uniID,
1779 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001780 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301781 }
1782
1783 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001784 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301785 log.Fields{
1786 "msg": *delTcontMsg,
1787 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001788 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301789 delTcontMsg,
1790 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001791 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 onuDev.deviceType,
1793 onuDev.deviceID,
1794 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301795 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1796 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001797 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301798 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1799 "proxyDeviceID": onuDev.proxyDeviceID,
1800 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301803 log.Fields{
1804 "msg": delTcontMsg,
1805 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301806 return nil
1807}
1808
Girish Gowdrac3037402020-01-22 20:29:53 +05301809// Once the gemport is released for a given onu, it also has to be cleared from local cache
1810// which was used for deriving the gemport->logicalPortNo during packet-in.
1811// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1812// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001814
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001815 f.onuGemInfoLock.Lock()
1816 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001817
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301819 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001820 "gem-port-id": gemPortID,
1821 "intf-id": intfID,
1822 "onu-id": onuID,
1823 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001824 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001825
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001826 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001827deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001828 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301829 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001830 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301831 // If the gemport is found, delete it from local cache.
1832 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001833 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1834 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
1837 "intf-id": intfID,
1838 "onu-id": onuID,
1839 "deletedgemport-id": gemPortID,
1840 "gemports": onu.GemPorts,
1841 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001842 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301843 }
1844 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001845 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301846 }
1847 }
1848}
1849
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301850//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001851// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301852func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001853 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001854
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001856 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301857 return olterrors.NewErrNotFound("tp-id",
1858 log.Fields{
1859 "flow": flow,
1860 "intf": Intf,
1861 "onu-id": onuID,
1862 "uni-id": uniID,
1863 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001864 }
Gamze Abakafee36392019-10-03 11:17:24 +00001865
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001866 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1867 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1868 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1869 log.Fields{
1870 "tpPath": tpPath,
1871 "device-id": f.deviceHandler.device.Id})
1872 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1873 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1874 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1875 log.Fields{
1876 "tp-id": tpID,
1877 "path": tpPath}, err)
1878 }
1879
1880 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1881
1882 if used {
1883 f.flowsUsedByGemPortKey.Lock()
1884 defer f.flowsUsedByGemPortKey.Unlock()
1885
1886 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1887 for i, flowIDinMap := range flowIDs {
1888 if flowIDinMap == flowID {
1889 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1890 // everytime flowsUsedByGemPort cache is updated the same should be updated
1891 // in kv store by calling UpdateFlowIDsForGem
1892 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1893 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1894 return err
1895 }
1896 break
1897 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001898 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001899 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1900 log.Fields{
1901 "gemport-id": gemPortID,
1902 "usedByFlows": flowIDs,
1903 "device-id": f.deviceHandler.device.Id})
1904 return nil
1905 }
1906 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1907 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1908 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1909 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1910 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Esin Karamandf392e12020-12-16 13:33:09 +00001911 // also clear gem to uni cache
1912 f.removeFromGemToUniMap(gemPortKey{
1913 intfID: Intf,
1914 gemPort: uint32(gemPortID),
1915 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001916 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001917
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001918 f.onuIdsLock.Lock() // TODO: What is this lock?
1919
1920 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1921 // by calling DeleteFlowIDsForGem
1922 f.flowsUsedByGemPortKey.Lock()
1923 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1924 f.flowsUsedByGemPortKey.Unlock()
1925 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1926 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1927
1928 f.onuIdsLock.Unlock()
1929
1930 // Delete the gem port on the ONU.
1931 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1932 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1933 log.Fields{
1934 "err": err,
1935 "intf": Intf,
1936 "onu-id": onuID,
1937 "uni-id": uniID,
1938 "device-id": f.deviceHandler.device.Id,
1939 "gemport-id": gemPortID})
1940 }
1941 switch techprofileInst := techprofileInst.(type) {
1942 case *tp.TechProfile:
1943 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1944 if !ok {
1945 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1946 logger.Warn(ctx, err)
1947 }
1948 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1949 logger.Warn(ctx, err)
1950 }
1951 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 {
1952 logger.Warn(ctx, err)
1953 }
1954 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 {
1955 logger.Warn(ctx, err)
1956 }
1957 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1958 // Delete the TCONT on the ONU.
1959 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1960 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1961 log.Fields{
1962 "intf": Intf,
1963 "onu-id": onuID,
1964 "uni-id": uniID,
1965 "device-id": f.deviceHandler.device.Id,
1966 "alloc-id": techprofileInst.UsScheduler.AllocID})
1967 }
1968 }
1969 case *tp.EponProfile:
1970 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1971 logger.Warn(ctx, err)
1972 }
1973 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1974 logger.Warn(ctx, err)
1975 }
1976 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1977 // Delete the TCONT on the ONU.
1978 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1979 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301980 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301982 "onu-id": onuID,
1983 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 "device-id": f.deviceHandler.device.Id,
1985 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 default:
1988 logger.Errorw(ctx, "error-unknown-tech",
1989 log.Fields{
1990 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301993 return nil
1994}
1995
David K. Bainbridge794735f2020-02-11 21:01:37 -08001996// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001997func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001998 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001999 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302000 log.Fields{
2001 "flowDirection": flowDirection,
2002 "flow": *flow,
2003 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002004
2005 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002006 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002007 }
2008
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302009 classifierInfo := make(map[string]interface{})
2010
Neha Sharma96b7bf22020-06-15 10:37:32 +00002011 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302012 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002013 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002014 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302015 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302016
David K. Bainbridge794735f2020-02-11 21:01:37 -08002017 onuID := int32(onu)
2018 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019
2020 for _, field := range flows.GetOfbFields(flow) {
2021 if field.Type == flows.IP_PROTO {
2022 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002023 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302024 }
2025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002026 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302027 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002028 "flow-id": flow.Id,
2029 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302030 "onu-id": onuID,
2031 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302032
2033 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2034 onuID = -1
2035 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002036 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2037 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002038 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002040 log.Fields{
2041 "port-number": inPort,
2042 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002043 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002044 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302045 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002046 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2047 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})
2048 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2049 }
2050 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2051 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2052 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2053 return err
2054 }
2055 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2056 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2057 return err
2058 }
2059 if !flowInfo.Flow.ReplicateFlow {
2060 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002061 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002062 "flow-id": flow.Id,
2063 "stored-flow": flowInfo.Flow,
2064 "device-id": f.deviceHandler.device.Id,
2065 "stored-flow-id": flowInfo.Flow.FlowId,
2066 "onu-id": onuID,
2067 "intf": Intf,
2068 })
2069 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302070 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002071 } else {
2072 gems := make([]uint32, 0)
2073 for _, gem := range flowInfo.Flow.PbitToGemport {
2074 gems = appendUnique32bit(gems, gem)
2075 }
2076 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2077 for _, gem := range gems {
2078 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002079 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002080 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002081 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002082 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002083 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002084 "onu-id": onuID,
2085 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002087 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002088 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302089 }
2090 }
2091 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002092
2093 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2094 if isDatapathFlow(flow) {
2095 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2096 var inverseDirection string
2097 if flowDirection == Upstream {
2098 inverseDirection = Downstream
2099 } else {
2100 inverseDirection = Upstream
2101 }
2102
2103 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002104 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002106 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002107 }
2108 }
2109 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002110}
2111
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002112//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002113func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002114
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302116 var direction string
2117 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002118
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302119 for _, action := range flows.GetActions(flow) {
2120 if action.Type == flows.OUTPUT {
2121 if out := action.GetOutput(); out != nil {
2122 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002123 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302124 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002125 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002126 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002127 }
2128 }
2129 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002130
2131 if flows.HasGroup(flow) {
2132 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002133 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002134 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302135 direction = Upstream
2136 } else {
2137 direction = Downstream
2138 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302139
Girish Gowdracefae192020-03-19 18:14:10 -07002140 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002141 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002142
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002143 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002144}
2145
Esin Karamanae41e2b2019-12-17 18:13:13 +00002146//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2147func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2148 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2149 if ethType, ok := classifierInfo[EthType]; ok {
2150 if ethType.(uint32) == IPv4EthType {
2151 if ipProto, ok := classifierInfo[IPProto]; ok {
2152 if ipProto.(uint32) == IgmpProto {
2153 return true
2154 }
2155 }
2156 }
2157 }
2158 }
2159 return false
2160}
2161
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002162// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2163func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2164 // Step1 : Fill flowControlBlock
2165 // Step2 : Push the flowControlBlock to ONU channel
2166 // Step3 : Wait on response channel for response
2167 // Step4 : Return error value
2168 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2169 errChan := make(chan error)
2170 flowCb := flowControlBlock{
2171 ctx: ctx,
2172 addFlow: addFlow,
2173 flow: flow,
2174 flowMetadata: flowMetadata,
2175 errChan: &errChan,
2176 }
2177 inPort, outPort := getPorts(flow)
2178 var onuID uint32
2179 if inPort != InvalidPort && outPort != InvalidPort {
2180 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2181 }
2182 // inPort or outPort is InvalidPort for trap-from-nni flows.
2183 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2184 // Send the flowCb on the ONU flow channel
2185 f.incomingFlows[onuID] <- flowCb
2186 // Wait on the channel for flow handlers return value
2187 err := <-errChan
2188 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2189 return err
2190}
2191
2192// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2193// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2194func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2195 for {
2196 // block on the channel to receive an incoming flow
2197 // process the flow completely before proceeding to handle the next flow
2198 flowCb := <-subscriberFlowChannel
2199 if flowCb.addFlow {
2200 logger.Debugw(flowCb.ctx, "adding-flow",
2201 log.Fields{"device-id": f.deviceHandler.device.Id,
2202 "flowToAdd": flowCb.flow})
2203 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2204 // Pass the return value over the return channel
2205 *flowCb.errChan <- err
2206 } else {
2207 logger.Debugw(flowCb.ctx, "removing-flow",
2208 log.Fields{"device-id": f.deviceHandler.device.Id,
2209 "flowToRemove": flowCb.flow})
2210 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2211 // Pass the return value over the return channel
2212 *flowCb.errChan <- err
2213 }
2214 }
2215}
2216
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002217// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302218// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002219func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002220 classifierInfo := make(map[string]interface{})
2221 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002222 var UsMeterID uint32
2223 var DsMeterID uint32
2224
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302226 log.Fields{
2227 "flow": flow,
2228 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002229 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002230
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002232 if err != nil {
2233 // Error logging is already done in the called function
2234 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002235 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302236 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002237
Esin Karamanccb714b2019-11-29 15:02:06 +00002238 if flows.HasGroup(flow) {
2239 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002240 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002241 }
2242
manikkaraj k17652a72019-05-06 09:06:36 -04002243 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002244 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002245 if err != nil {
2246 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002247 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002248 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002249
Neha Sharma96b7bf22020-06-15 10:37:32 +00002250 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302251 log.Fields{
2252 "classifierinfo_inport": classifierInfo[InPort],
2253 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002254 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002255
Humera Kouser94d7a842019-08-25 19:04:32 -04002256 if ethType, ok := classifierInfo[EthType]; ok {
2257 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002260 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002261 if ethType.(uint32) == PPPoEDEthType {
2262 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2263 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2264 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2265 }
2266 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002267 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002268 if ipProto, ok := classifierInfo[IPProto]; ok {
2269 if ipProto.(uint32) == IPProtoDhcp {
2270 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302271 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002272 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002273 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002274 }
2275 }
2276 }
2277 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002278 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002280 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002281 }
A R Karthick1f85b802019-10-11 05:06:05 +00002282
npujarec5762e2020-01-01 14:08:48 +05302283 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002284
Neha Sharma96b7bf22020-06-15 10:37:32 +00002285 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002286 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302287 return olterrors.NewErrNotFound("tpid-for-flow",
2288 log.Fields{
2289 "flow": flow,
2290 "intf-id": IntfID,
2291 "onu-id": onuID,
2292 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002293 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302295 log.Fields{
2296 "tp-id": TpID,
2297 "intf-id": intfID,
2298 "onu-id": onuID,
2299 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002300 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002301 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002303 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002304 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002305 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002306
2307 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002308 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002309}
Girish Gowdra3d633032019-12-10 16:37:05 +05302310
Esin Karamanccb714b2019-11-29 15:02:06 +00002311// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002312func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002313 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302315 "classifier-info": classifierInfo,
2316 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002317
Esin Karaman65409d82020-03-18 10:58:18 +00002318 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002319 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002320 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002321 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002322
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002323 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002324
David K. Bainbridge794735f2020-02-11 21:01:37 -08002325 onuID := NoneOnuID
2326 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002327
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002328 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002330 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002331 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002332 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2333 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002334 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002335 }
2336 groupID := actionInfo[GroupID].(uint32)
2337 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002338 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002339 FlowType: Multicast,
2340 NetworkIntfId: int32(networkInterfaceID),
2341 GroupId: groupID,
2342 Classifier: classifierProto,
2343 Priority: int32(flow.Priority),
2344 Cookie: flow.Cookie}
2345
Kent Hagermane6ff1012020-07-14 15:07:53 -04002346 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002347 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002348 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002349 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002350 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002351 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002352 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002353 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002354 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002356 //cached group can be removed now
2357 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2358 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2359 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002360 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002361
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002362 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2363 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2364 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002365 }
2366 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002367}
2368
Esin Karaman65409d82020-03-18 10:58:18 +00002369//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2370func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2371 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002373 if err != nil {
2374 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2375 }
2376 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002377 }
Esin Karaman65409d82020-03-18 10:58:18 +00002378 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302379 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002380 if e == nil && len(nniPorts) > 0 {
2381 return nniPorts[0], nil
2382 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302383 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002384}
2385
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002386//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302390 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302392 log.Fields{
2393 "intf-id": intfID,
2394 "onu-id": onuID,
2395 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002396 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302397 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002398 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002399
Neha Sharma96b7bf22020-06-15 10:37:32 +00002400 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002401 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002403 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002404 tpDownloadMsg,
2405 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002406 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002407 onuDev.deviceType,
2408 onuDev.deviceID,
2409 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002410 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302411 return olterrors.NewErrCommunication("send-techprofile-download-request",
2412 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002413 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302414 "to-adapter": onuDev.deviceType,
2415 "onu-id": onuDev.deviceID,
2416 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002417 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302419 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302420}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002421
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302422//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002423func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302424
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002425 f.onuGemInfoLock.Lock()
2426 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002427 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002428 // If the ONU already exists in onuGemInfo list, nothing to do
2429 for _, onu := range onugem {
2430 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2431 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2432 log.Fields{"onuID": onuID,
2433 "serialNum": serialNum})
2434 return nil
2435 }
2436 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002437
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302438 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002439 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002440 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002441 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302442 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302444 log.Fields{
2445 "intf-id": intfID,
2446 "onu-id": onuID,
2447 "serial-num": serialNum,
2448 "onu": onu,
2449 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002450 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002451}
2452
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302453//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302454func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002455
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002456 f.onuGemInfoLock.Lock()
2457 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002458
Neha Sharma96b7bf22020-06-15 10:37:32 +00002459 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302460 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002461 "gem-port-id": gemPort,
2462 "intf-id": intfID,
2463 "onu-id": onuID,
2464 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002465 "onu-gem": f.onuGemInfo})
2466 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302467 // update the gem to the local cache as well as to kv strore
2468 for idx, onu := range onugem {
2469 if onu.OnuID == onuID {
2470 // check if gem already exists , else update the cache and kvstore
2471 for _, gem := range onu.GemPorts {
2472 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302474 log.Fields{
2475 "gem": gemPort,
2476 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302477 return
2478 }
2479 }
2480 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002481 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002482 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302483 }
2484 }
npujarec5762e2020-01-01 14:08:48 +05302485 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302486 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002487 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302488 log.Fields{
2489 "intf-id": intfID,
2490 "onu-id": onuID,
2491 "gemPort": gemPort,
2492 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002493 return
2494 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002495 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302496 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002497 "gem-port-id": gemPort,
2498 "intf-id": intfID,
2499 "onu-id": onuID,
2500 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002501 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002502}
2503
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002504//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302505func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002506 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002507 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002508 var err error
2509
2510 if packetIn.IntfType == "pon" {
2511 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002512 // get onu and uni ids associated with the given pon and gem ports
2513 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002514 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002515 return logicalPortNum, err
2516 }
Esin Karamandf392e12020-12-16 13:33:09 +00002517 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2518
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002519 if packetIn.PortNo != 0 {
2520 logicalPortNum = packetIn.PortNo
2521 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002522 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002523 }
2524 // 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 +00002525 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002526 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002527 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002528 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002529
2530 if logger.V(log.DebugLevel) {
2531 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2532 log.Fields{
2533 "logical-port-num": logicalPortNum,
2534 "intf-type": packetIn.IntfType,
2535 "packet": hex.EncodeToString(packetIn.Pkt),
2536 })
2537 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538 return logicalPortNum, nil
2539}
2540
Esin Karamandf392e12020-12-16 13:33:09 +00002541//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2542func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2543 key := gemPortKey{
2544 intfID: intfID,
2545 gemPort: gemPortID,
2546 }
2547 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2548 if ok {
2549 if len(uniPortInfo) > 1 {
2550 //return onu ID and uni port from the cache
2551 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2552 log.Fields{
2553 "intfID": intfID,
2554 "gemPortID": gemPortID,
2555 "onuID, uniID": uniPortInfo})
2556 return uniPortInfo[0], uniPortInfo[1], nil
2557 }
2558 }
2559 //If uni port is not found in cache try to get it from kv store. if it is found in kv store, update the cache and return.
2560 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2561 if err == nil {
2562 f.toGemToUniMap(ctx, key, onuID, uniID)
2563 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2564 log.Fields{
2565 "gemPortKey": key,
2566 "onuID": onuID,
2567 "uniID": uniID})
2568 return onuID, uniID, nil
2569 }
2570 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2571 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2572 errors.New("no uni port found"))
2573}
2574
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002575//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002576func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002577 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002578
2579 ctag, priority, err := getCTagFromPacket(ctx, packet)
2580 if err != nil {
2581 return 0, err
2582 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302583
Esin Karaman7fb80c22020-07-16 14:23:33 +00002584 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002585 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002586 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002587 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002588 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302589 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002590 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302591 log.Fields{
2592 "pktinkey": pktInkey,
2593 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002594
2595 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302597 //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 +00002598 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302599 if err == nil {
2600 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002601 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302602 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002603 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302605 log.Fields{
2606 "pktinkey": pktInkey,
2607 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302608 return gemPortID, nil
2609 }
2610 }
Shrey Baid26912972020-04-16 21:02:31 +05302611 return uint32(0), olterrors.NewErrNotFound("gem-port",
2612 log.Fields{
2613 "pktinkey": pktInkey,
2614 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002615
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002616}
2617
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002618func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2619 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002621 classifier[PacketTagType] = DoubleTag
2622 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002623 /* We manage flowId resource pool on per PON port basis.
2624 Since this situation is tricky, as a hack, we pass the NNI port
2625 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002626 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002627 on NNI port, use onu_id as -1 (invalid)
2628 ****************** CAVEAT *******************
2629 This logic works if the NNI Port Id falls within the same valid
2630 range of PON Port Ids. If this doesn't work for some OLT Vendor
2631 we need to have a re-look at this.
2632 *********************************************
2633 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002634 onuID := -1
2635 uniID := -1
2636 gemPortID := -1
2637 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002638 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302639 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302640 return olterrors.NewErrNotFound("nni-intreface-id",
2641 log.Fields{
2642 "classifier": classifier,
2643 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002644 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302645 }
2646
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002647 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002648 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002649 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002650 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002651
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002652 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2653 log.Fields{
2654 "classifier": classifier,
2655 "action": action,
2656 "flowId": logicalFlow.Id,
2657 "intf-id": networkInterfaceID})
2658
David K. Bainbridge794735f2020-02-11 21:01:37 -08002659 classifierProto, err := makeOpenOltClassifierField(classifier)
2660 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002661 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002662 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002663 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002664 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002665 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002666 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002667 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002668 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002669 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2670 OnuId: int32(onuID), // OnuId not required
2671 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002672 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002673 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002674 AllocId: int32(allocID), // AllocId not used
2675 NetworkIntfId: int32(networkInterfaceID),
2676 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002677 Classifier: classifierProto,
2678 Action: actionProto,
2679 Priority: int32(logicalFlow.Priority),
2680 Cookie: logicalFlow.Cookie,
2681 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002682 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002683 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002685 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2687 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2688 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 }
2690 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002691}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002692
Esin Karamanae41e2b2019-12-17 18:13:13 +00002693//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2694func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2695 var packetType string
2696 ovid, ivid := false, false
2697 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2698 vid := vlanID & VlanvIDMask
2699 if vid != ReservedVlan {
2700 ovid = true
2701 }
2702 }
2703 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2704 vid := uint32(metadata)
2705 if vid != ReservedVlan {
2706 ivid = true
2707 }
2708 }
2709 if ovid && ivid {
2710 packetType = DoubleTag
2711 } else if !ovid && !ivid {
2712 packetType = Untagged
2713 } else {
2714 packetType = SingleTag
2715 }
2716 return packetType
2717}
2718
2719//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002720func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002722 action := make(map[string]interface{})
2723 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2724 action[TrapToHost] = true
2725 /* We manage flowId resource pool on per PON port basis.
2726 Since this situation is tricky, as a hack, we pass the NNI port
2727 index (network_intf_id) as PON port Index for the flowId resource
2728 pool. Also, there is no ONU Id available for trapping packets
2729 on NNI port, use onu_id as -1 (invalid)
2730 ****************** CAVEAT *******************
2731 This logic works if the NNI Port Id falls within the same valid
2732 range of PON Port Ids. If this doesn't work for some OLT Vendor
2733 we need to have a re-look at this.
2734 *********************************************
2735 */
2736 onuID := -1
2737 uniID := -1
2738 gemPortID := -1
2739 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002740 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002741 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302742 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002743 "classifier": classifier,
2744 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002745 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002746 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002747 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002748 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002749 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002750 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002751
David K. Bainbridge794735f2020-02-11 21:01:37 -08002752 classifierProto, err := makeOpenOltClassifierField(classifier)
2753 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002754 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002755 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002756 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002757 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002758 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002759 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002760 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002761 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002762 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2763 OnuId: int32(onuID), // OnuId not required
2764 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002765 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002766 FlowType: Downstream,
2767 AllocId: int32(allocID), // AllocId not used
2768 NetworkIntfId: int32(networkInterfaceID),
2769 GemportId: int32(gemPortID), // GemportId not used
2770 Classifier: classifierProto,
2771 Action: actionProto,
2772 Priority: int32(logicalFlow.Priority),
2773 Cookie: logicalFlow.Cookie,
2774 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002775 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002777 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002778 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002779 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2780 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2781 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 }
2783 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784}
2785
salmansiddiqui7ac62132019-08-22 03:58:50 +00002786func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2787 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302788 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002789 }
2790 if Dir == tp_pb.Direction_UPSTREAM {
2791 return "upstream", nil
2792 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2793 return "downstream", nil
2794 }
2795 return "", nil
2796}
2797
Kent Hagermane6ff1012020-07-14 15:07:53 -04002798// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302799func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002800 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002801 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002802 var gemPort uint32
2803 intfID := args[IntfID]
2804 onuID := args[OnuID]
2805 uniID := args[UniID]
2806 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002807 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002808 pbitToGem := make(map[uint32]uint32)
2809
2810 if len(gemPorts) == 1 {
2811 // If there is only single gemport use that and do not populate pbitToGem map
2812 gemPort = gemPorts[0]
2813 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2814 for idx, gemID := range gemPorts {
2815 switch TpInst := TpInst.(type) {
2816 case *tp.TechProfile:
2817 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2818 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2819 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2820 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2821 // this pcp bit traffic.
2822 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2823 if pbitSet == pbit1 {
2824 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2825 pbitToGem[pcp] = gemID
2826 }
2827 }
2828 default:
2829 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2830 return
2831 }
2832 }
2833 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2834 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2835 tp_pb.Direction_UPSTREAM,
2836 pcp.(uint32))
2837 }
2838
salmansiddiqui7ac62132019-08-22 03:58:50 +00002839 if ipProto, ok := classifierInfo[IPProto]; ok {
2840 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002841 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002842 "tp-id": tpID,
2843 "alloc-id": allocID,
2844 "intf-id": intfID,
2845 "onu-id": onuID,
2846 "uni-id": uniID,
2847 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848 //Adding DHCP upstream flow
2849 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2850 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002851 }
2852
Girish Gowdra32625212020-04-29 11:26:35 -07002853 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002854 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302855 log.Fields{
2856 "intf-id": intfID,
2857 "onu-id": onuID,
2858 "uni-id": uniID,
2859 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002860 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2861 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002862 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002863 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002864 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 return
2866 }
2867 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002868 if ethType.(uint32) == EapEthType || ethType.(uint32) == PPPoEDEthType {
2869 logger.Infow(ctx, "adding-ethType-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002870 "intf-id": intfID,
2871 "onu-id": onuID,
2872 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002873 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002874 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002875 var vlanID uint32
2876 if val, ok := classifierInfo[VlanVid]; ok {
2877 vlanID = (val.(uint32)) & VlanvIDMask
2878 } else {
2879 vlanID = DefaultMgmtVlan
2880 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002881 if err := f.addEthTypeBasedFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002882 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 }
2884 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002885 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002886 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002887 "intf-id": intfID,
2888 "onu-id": onuID,
2889 "uni-id": uniID,
2890 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002891 //Adding HSIA upstream flow
2892 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2893 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002894 }
2895 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002897 "intf-id": intfID,
2898 "onu-id": onuID,
2899 "uni-id": uniID,
2900 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901 //Adding HSIA downstream flow
2902 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2903 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002904 }
2905 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302907 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302911 "classifier": classifierInfo,
2912 "action": actionInfo,
2913 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 return
2915 }
2916 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002917 go func() {
2918 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2919 logger.Warn(ctx, err)
2920 }
2921 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922}
2923
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002924func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2925 f.flowsUsedByGemPortKey.RLock()
2926 flowIDList := f.flowsUsedByGemPort[gemPortID]
2927 f.flowsUsedByGemPortKey.RUnlock()
2928 return len(flowIDList) > 1
2929
Gamze Abakafee36392019-10-03 11:17:24 +00002930}
2931
npujarec5762e2020-01-01 14:08:48 +05302932func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2933 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002934 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2935 for _, currentGemPort := range currentGemPorts {
2936 for _, tpGemPort := range tpGemPorts {
2937 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2938 return true, currentGemPort
2939 }
2940 }
2941 }
Girish Gowdra54934262019-11-13 14:19:55 +05302942 if tpInst.InstanceCtrl.Onu == "single-instance" {
2943 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002944 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002945 logger.Warn(ctx, err)
2946 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002947 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002948 logger.Warn(ctx, err)
2949 }
Girish Gowdra54934262019-11-13 14:19:55 +05302950
2951 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2952 // still be used on other uni ports.
2953 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2954 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002955 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002956 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302957 for i := 0; i < len(tpInstances); i++ {
2958 tpI := tpInstances[i]
2959 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302960 for _, tpGemPort := range tpGemPorts {
2961 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302963 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302964 }
2965 }
2966 }
2967 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002969 return false, 0
2970}
2971
Neha Sharma96b7bf22020-06-15 10:37:32 +00002972func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002973 for _, field := range flows.GetOfbFields(flow) {
2974 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002977 } else if field.Type == flows.ETH_DST {
2978 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002980 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002981 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002983 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002984 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002986 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302987 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002989 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002990 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002992 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002995 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002996 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002997 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002998 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002999 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003000 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003001 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003004 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003005 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003006 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003007 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003008 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003010 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 return
3013 }
3014 }
3015}
3016
Neha Sharma96b7bf22020-06-15 10:37:32 +00003017func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003018 for _, action := range flows.GetActions(flow) {
3019 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003021 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003023 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003024 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003025 }
Scott Baker355d1742019-10-24 10:57:52 -07003026 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003029 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 if out := action.GetPush(); out != nil {
3031 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 } else {
3034 actionInfo[PushVlan] = true
3035 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303037 log.Fields{
3038 "push-tpid": actionInfo[TPID].(uint32),
3039 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003040 }
3041 }
Scott Baker355d1742019-10-24 10:57:52 -07003042 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 if out := action.GetSetField(); out != nil {
3044 if field := out.GetField(); field != nil {
3045 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003046 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3049 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 }
3051 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003052 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003055 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 }
3057 }
3058 return nil
3059}
3060
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003062 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003063 fieldtype := ofbField.GetType()
3064 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003065 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3066 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003068 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003070 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003071 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3072 pcp := ofbField.GetVlanPcp()
3073 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003074 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003075 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003077 }
3078 }
3079}
3080
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003082 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003084 } else {
3085 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003087 }
3088}
3089
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003091 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003092 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3094 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003095 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303098 log.Fields{
3099 "newinport": classifierInfo[InPort].(uint32),
3100 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303102 return olterrors.NewErrNotFound("child-in-port",
3103 log.Fields{
3104 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3105 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 }
3107 }
3108 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003110 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003111 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003112 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003113 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303115 log.Fields{
3116 "newoutport": actionInfo[Output].(uint32),
3117 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303119 return olterrors.NewErrNotFound("out-port",
3120 log.Fields{
3121 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3122 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 }
3124 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3125 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003126 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303129 log.Fields{
3130 "newinport": actionInfo[Output].(uint32),
3131 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303133 return olterrors.NewErrNotFound("nni-port",
3134 log.Fields{
3135 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3136 "in-port": classifierInfo[InPort].(uint32),
3137 "out-port": actionInfo[Output].(uint32),
3138 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003139 }
3140 }
3141 }
3142 return nil
3143}
Gamze Abakafee36392019-10-03 11:17:24 +00003144
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003146 /* Metadata 8 bytes:
3147 Most Significant 2 Bytes = Inner VLAN
3148 Next 2 Bytes = Tech Profile ID(TPID)
3149 Least Significant 4 Bytes = Port ID
3150 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3151 subscriber related flows.
3152 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003153 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003154 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003155 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003156 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003157 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003158 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003159}
3160
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003161func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3162 for _, sliceElement := range slice {
3163 if sliceElement == item {
3164 return slice
3165 }
3166 }
3167 return append(slice, item)
3168}
3169
3170func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003171 for _, sliceElement := range slice {
3172 if sliceElement == item {
3173 return slice
3174 }
3175 }
3176 return append(slice, item)
3177}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303178
3179// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303181
3182 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3183 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003185 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003187 log.Fields{
3188 "port-number": action[Output].(uint32),
3189 "error": err})
3190 return uint32(0), err
3191 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003192 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303193 return intfID, nil
3194 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003195 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003196 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003197 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003198 log.Fields{
3199 "port-number": action[Output].(uint32),
3200 "error": err})
3201 return uint32(0), err
3202 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003203 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303204 return intfID, nil
3205 }
3206 return uint32(0), nil
3207}
3208
3209// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003210func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3211 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3212 if err != nil {
3213 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3214 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3215 return
3216 }
3217 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003218
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003219 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003220 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003221 f.packetInGemPortLock.RUnlock()
3222
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303223 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003224 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 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 +05303226 log.Fields{
3227 "pktinkey": pktInkey,
3228 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003229 return
3230 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303231 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003232 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003233 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003234 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003235
npujarec5762e2020-01-01 14:08:48 +05303236 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237 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 +05303238 log.Fields{
3239 "pktinkey": pktInkey,
3240 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303241}
3242
Esin Karaman7fb80c22020-07-16 14:23:33 +00003243//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3244func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3245 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003246 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003247 return 0, 0, errors.New("invalid packet length")
3248 }
3249 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3250 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3251
3252 var index int8
3253 if outerEthType == 0x8100 {
3254 if innerEthType == 0x8100 {
3255 // q-in-q 802.1ad or 802.1q double tagged packet.
3256 // get the inner vlanId
3257 index = 18
3258 } else {
3259 index = 14
3260 }
3261 priority := (packet[index] >> 5) & 0x7
3262 //13 bits composes vlanId value
3263 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3264 return vlan, priority, nil
3265 }
3266 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3267 return 0, 0, nil
3268}
3269
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303270// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303271func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003272
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003273 f.onuGemInfoLock.Lock()
3274 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003275
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003276 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303277 for idx, onu := range onugem {
3278 if onu.OnuID == onuID {
3279 for _, uni := range onu.UniPorts {
3280 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003281 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 +05303282 return
3283 }
3284 }
3285 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003286 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303287 }
3288 }
npujarec5762e2020-01-01 14:08:48 +05303289 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003290
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303291}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303292
npujarec5762e2020-01-01 14:08:48 +05303293func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3294 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303295 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003296 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303297 return
3298 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003299 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303300 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003301 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303302 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003303 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303304}
Esin Karamanccb714b2019-11-29 15:02:06 +00003305
Girish Gowdra9602eb42020-09-09 15:50:39 -07003306//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3307// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003308func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003309 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003310 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003311 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3312 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3313
Esin Karamanccb714b2019-11-29 15:02:06 +00003314 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003315 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 -07003316 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003317 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003318
3319 var onuID = int32(NoneOnuID)
3320 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003321 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3322 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3323 log.Fields{
3324 "flow": flow,
3325 "device-id": f.deviceHandler.device.Id,
3326 "intf-id": networkInterfaceID,
3327 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003328 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003329 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3330 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3331 log.Fields{
3332 "flow": flowInfo.Flow,
3333 "flow-id": flow.Id,
3334 "device-id": f.deviceHandler.device.Id})
3335 // Remove from device
3336 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3337 // DKB
3338 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3339 log.Fields{
3340 "flow-id": flow.Id,
3341 "error": err})
3342 return err
3343 }
3344 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003345 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003346}
3347
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003348// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3349func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3350 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3351 if err != nil {
3352 _ = olterrors.NewErrNotFound("onu", log.Fields{
3353 "pon-port": f.ponPortIdx}, err).Log()
3354 return
3355 }
3356
3357 f.subscriberDataPathFlowIDMapLock.Lock()
3358 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3359
3360 for _, onu := range onuGemInfo {
3361 for _, uniID := range onu.UniPorts {
3362 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3363 if err != nil {
3364 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3365 }
3366 for _, flowID := range flowIDs {
3367 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3368 if flowInfo == nil {
3369 // Error is already logged in the called function
3370 continue
3371 }
3372 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3373 flowInfo.Flow.FlowType == Downstream &&
3374 flowInfo.Flow.Classifier.OVid > 0 &&
3375 flowInfo.Flow.TechProfileId > 0 {
3376 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3377 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3378 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3379 }
3380 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3381 flowInfo.Flow.FlowType == Upstream &&
3382 flowInfo.Flow.Action.OVid > 0 &&
3383 flowInfo.Flow.TechProfileId > 0 {
3384 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3385 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3386 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3387 }
3388 }
3389 }
3390 }
3391 }
3392}
3393
3394// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3395func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3396 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3397}