blob: 15c7e9cf99bf9c9b9733b2ef6ec675b24eae5ab1 [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"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
28
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
30 "github.com/opencord/voltha-lib-go/v4/pkg/log"
31 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080032 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070033 "github.com/opencord/voltha-protos/v4/go/common"
34 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
35 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
36 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
37 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
38 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040039
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000041 "google.golang.org/grpc/codes"
42 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053043)
44
45const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //IPProtoDhcp flow category
47 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdraa09aeab2020-09-14 16:30:52 -070049 //IgmpProto proto value
50 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051
52 //EapEthType eapethtype value
53 EapEthType = 0x888e
54 //LldpEthType lldp ethtype value
55 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000056 //IPv4EthType IPv4 ethernet type value
57 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030058 //PPPoEDEthType PPPoE discovery ethernet type value
59 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060
Andrea Campanella7acc0b92020-02-14 09:20:49 +010061 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
62 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064 //DefaultMgmtVlan default vlan value
65 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053066
manikkaraj kbf256be2019-03-25 00:13:48 +053067 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068
David K. Bainbridge82efc492019-09-04 09:57:11 -070069 //Upstream constant
70 Upstream = "upstream"
71 //Downstream constant
72 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000073 //Multicast constant
74 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 //PacketTagType constant
76 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070077 //Untagged constant
78 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //SingleTag constant
80 SingleTag = "single_tag"
81 //DoubleTag constant
82 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053083
84 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085
86 //EthType constant
87 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000088 //EthDst constant
89 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090 //TPID constant
91 TPID = "tpid"
92 //IPProto constant
93 IPProto = "ip_proto"
94 //InPort constant
95 InPort = "in_port"
96 //VlanVid constant
97 VlanVid = "vlan_vid"
98 //VlanPcp constant
99 VlanPcp = "vlan_pcp"
100
101 //UDPDst constant
102 UDPDst = "udp_dst"
103 //UDPSrc constant
104 UDPSrc = "udp_src"
105 //Ipv4Dst constant
106 Ipv4Dst = "ipv4_dst"
107 //Ipv4Src constant
108 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700109 //Metadata constant
110 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 //TunnelID constant
112 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Output constant
114 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000115 //GroupID constant
116 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 // Actions
118
119 //PopVlan constant
120 PopVlan = "pop_vlan"
121 //PushVlan constant
122 PushVlan = "push_vlan"
123 //TrapToHost constant
124 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400125 //MaxMeterBand constant
126 MaxMeterBand = 2
127 //VlanPCPMask contant
128 VlanPCPMask = 0xFF
129 //VlanvIDMask constant
130 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000131 //IntfID constant
132 IntfID = "intfId"
133 //OnuID constant
134 OnuID = "onuId"
135 //UniID constant
136 UniID = "uniId"
137 //PortNo constant
138 PortNo = "portNo"
139 //AllocID constant
140 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000141 //GemID constant
142 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000143
144 //NoneOnuID constant
145 NoneOnuID = -1
146 //NoneUniID constant
147 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700148
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700149 // Max number of flows that can be queued per ONU
150 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530151
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700152 bitMapPrefix = "0b"
153 pbit1 = '1'
154)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400155
Esin Karamandf392e12020-12-16 13:33:09 +0000156type gemPortKey struct {
157 intfID uint32
158 gemPort uint32
159}
160
Gamze Abakafee36392019-10-03 11:17:24 +0000161type schedQueue struct {
162 direction tp_pb.Direction
163 intfID uint32
164 onuID uint32
165 uniID uint32
166 tpID uint32
167 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700168 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000169 meterID uint32
170 flowMetadata *voltha.FlowMetadata
171}
172
Gamze Abaka7650be62021-02-26 10:50:36 +0000173type flowContext struct {
174 intfID uint32
175 onuID uint32
176 uniID uint32
177 portNo uint32
178 classifier map[string]interface{}
179 action map[string]interface{}
180 logicalFlow *ofp.OfpFlowStats
181 allocID uint32
182 gemPortID uint32
183 tpID uint32
184 pbitToGem map[uint32]uint32
185 gemToAes map[uint32]bool
186}
187
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700188// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
189type subscriberDataPathFlowIDKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193 direction string
194 tpID uint32
195}
196
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700197// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
198// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
199// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
200// flow and processes it serially
201type flowControlBlock struct {
202 ctx context.Context // Flow handler context
203 addFlow bool // if true flow to be added, else removed
204 flow *voltha.OfpFlowStats // Flow message
205 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
206 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000207}
208
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530210type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700211 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
212 techprofile map[uint32]tp.TechProfileIf
213 deviceHandler *DeviceHandler
214 grpMgr *OpenOltGroupMgr
215 resourceMgr *rsrcMgr.OpenOltResourceMgr
216
217 onuIdsLock sync.RWMutex // TODO: Do we need this?
218
219 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
220 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
221
222 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
223 packetInGemPortLock sync.RWMutex
224
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700225 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700227 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700228 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
231 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
232 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
233 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700234
235 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
236 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
237 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000238
239 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
240 gemToUniMap map[gemPortKey][]uint32
241 //We need to have a global lock on the gemToUniLock map
242 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530243}
244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700246func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000247 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530248 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 var err error
250 var idx uint32
251
manikkaraj kbf256be2019-03-25 00:13:48 +0530252 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700253 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000255 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000256 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
257 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530258 return nil
259 }
William Kurkian740a09c2019-10-23 17:07:38 -0400260 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700261 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700263 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700264 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700265 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
266 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700267
268 // Create a slice of buffered channels for handling concurrent flows per ONU.
269 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
270 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
271 for i := range flowMgr.incomingFlows {
272 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
273 // Spin up a go routine to handling incoming flows (add/remove).
274 // There will be on go routine per ONU.
275 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
276 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
277 }
278
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530279 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700280 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
281 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530282 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700283 //Load flowID list per gem map per interface from the kvstore.
284 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000285 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000286
287 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
288 flowMgr.gemToUniLock = sync.RWMutex{}
289
Girish Gowdra9602eb42020-09-09 15:50:39 -0700290 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700291 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000292 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530293 return &flowMgr
294}
295
Esin Karamandf392e12020-12-16 13:33:09 +0000296// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
297func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
298 f.gemToUniLock.Lock()
299 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
300 f.gemToUniLock.Unlock()
301}
302
303// fromGemToUniMap returns onu and uni ID associated with the given key
304func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
305 f.gemToUniLock.RLock()
306 defer f.gemToUniLock.RUnlock()
307 val, ok := f.gemToUniMap[key]
308 return val, ok
309}
310
311// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
312func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
313 f.gemToUniLock.Lock()
314 defer f.gemToUniLock.Unlock()
315 delete(f.gemToUniMap, key)
316}
317
Kent Hagermane6ff1012020-07-14 15:07:53 -0400318func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700319 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
320 // Flow is not replicated in this case, we need to register the flow for a single gem-port
321 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
322 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
323 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
324 for _, gemPort := range deviceFlow.PbitToGemport {
325 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
326 return err
327 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700328 }
Gamze Abakafee36392019-10-03 11:17:24 +0000329 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700330 return nil
331}
332
333func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
334 f.flowsUsedByGemPortKey.Lock()
335 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
336 if !ok {
337 flowIDList = []uint64{flowFromCore.Id}
338 }
339 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
340 f.flowsUsedByGemPort[gemPortID] = flowIDList
341 f.flowsUsedByGemPortKey.Unlock()
342
343 // update the flowids for a gem to the KVstore
344 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400345}
346
Girish Gowdra9602eb42020-09-09 15:50:39 -0700347func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000348 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200349 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000350 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530351 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700352 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530353
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530355 "device-id": f.deviceHandler.device.Id,
356 "intf-id": intfID,
357 "onu-id": onuID,
358 "uni-id": uniID,
359 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700360 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530361 "action": actionInfo,
362 "usmeter-iD": UsMeterID,
363 "dsmeter-iD": DsMeterID,
364 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400365 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
366 // is because the flow is an NNI flow and there would be no onu resources associated with it
367 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400368 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200369 cause := "no-onu-id-for-flow"
370 fields := log.Fields{
371 "onu": onuID,
372 "port-no": portNo,
373 "classifer": classifierInfo,
374 "action": actionInfo,
375 "device-id": f.deviceHandler.device.Id}
376 logger.Errorw(ctx, cause, fields)
377 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530378 }
379
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700380 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000381 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530382 "uni": uni,
383 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530384
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700385 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
386 "device-id": f.deviceHandler.device.Id,
387 "intf-id": intfID,
388 "onu-id": onuID,
389 "uni-id": uniID,
390 "port-no": portNo,
391 "classifier": classifierInfo,
392 "action": actionInfo,
393 "usmeter-id": UsMeterID,
394 "dsmeter-id": DsMeterID,
395 "tp-id": TpID})
396 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
397 if allocID == 0 || gemPorts == nil || TpInst == nil {
398 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
399 return olterrors.NewErrNotFound(
400 "alloc-id-gem-ports-tp-unavailable",
401 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700403 args := make(map[string]uint32)
404 args[IntfID] = intfID
405 args[OnuID] = onuID
406 args[UniID] = uniID
407 args[PortNo] = portNo
408 args[AllocID] = allocID
409
410 /* Flows can be added specific to gemport if p-bits are received.
411 * If no pbit mentioned then adding flows for all gemports
412 */
413 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
414
Andrea Campanellabfe08432020-09-11 17:07:03 +0200415 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530416}
417
salmansiddiqui7ac62132019-08-22 03:58:50 +0000418// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530419func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420
Neha Sharma96b7bf22020-06-15 10:37:32 +0000421 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530422 log.Fields{"dir": sq.direction,
423 "intf-id": sq.intfID,
424 "onu-id": sq.onuID,
425 "uni-id": sq.uniID,
426 "tp-id": sq.tpID,
427 "meter-id": sq.meterID,
428 "tp-inst": sq.tpInst,
429 "flowmetadata": sq.flowMetadata,
430 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431
Gamze Abakafee36392019-10-03 11:17:24 +0000432 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000433 if err != nil {
434 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 }
436
437 /* Lets make a simple assumption that if the meter-id is present on the KV store,
438 * then the scheduler and queues configuration is applied on the OLT device
439 * in the given direction.
440 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000441
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700443 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530445 return olterrors.NewErrNotFound("meter",
446 log.Fields{"intf-id": sq.intfID,
447 "onu-id": sq.onuID,
448 "uni-id": sq.uniID,
449 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000451
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 if meterInfo != nil {
453 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
454 if meterInfo.MeterConfig.MeterId == sq.meterID {
455 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
456 return err
457 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400458 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530460 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800461 "unsupported": "meter-id",
Girish Gowdraa482f272021-03-24 23:04:19 -0700462 "kv-store-meter-id": meterInfo.MeterConfig.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530463 "meter-id-in-flow": sq.meterID,
464 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000466
Neha Sharma96b7bf22020-06-15 10:37:32 +0000467 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530468 log.Fields{
469 "meter-id": sq.meterID,
470 "direction": Direction,
471 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000472
Gamze Abakafee36392019-10-03 11:17:24 +0000473 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000475 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000476 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400477 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000478
479 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530480 return olterrors.NewErrNotFound("scheduler-config",
481 log.Fields{
482 "intf-id": sq.intfID,
483 "direction": sq.direction,
484 "tp-inst": sq.tpInst,
485 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000486 }
487
Girish Gowdraa482f272021-03-24 23:04:19 -0700488 found := false
489 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000490 if sq.flowMetadata != nil {
491 for _, meter := range sq.flowMetadata.Meters {
492 if sq.meterID == meter.MeterId {
Girish Gowdraa482f272021-03-24 23:04:19 -0700493 meterInfo.MeterConfig = ofp.OfpMeterConfig{}
494 meterInfo.MeterConfig.MeterId = meter.MeterId
495 meterInfo.MeterConfig.Flags = meter.Flags
496 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
497 meterInfo.MeterConfig.Bands = append(meterInfo.MeterConfig.Bands, meter.Bands...)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000498 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdraa482f272021-03-24 23:04:19 -0700499 log.Fields{"meterConfig": meterInfo.MeterConfig,
Shrey Baid26912972020-04-16 21:02:31 +0530500 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400502 break
503 }
504 }
505 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700508 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530509 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800510 "reason": "Could-not-get-meterbands-from-flowMetadata",
511 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530512 "meter-id": sq.meterID,
513 "device-id": f.deviceHandler.device.Id}, nil)
Girish Gowdraa482f272021-03-24 23:04:19 -0700514 } else if len(meterInfo.MeterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000515 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Girish Gowdraa482f272021-03-24 23:04:19 -0700516 log.Fields{"Bands": meterInfo.MeterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530517 "meter-id": sq.meterID,
518 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530519 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800520 "reason": "Invalid-number-of-bands-in-meter",
Girish Gowdraa482f272021-03-24 23:04:19 -0700521 "meterband-count": len(meterInfo.MeterConfig.Bands),
522 "metabands": meterInfo.MeterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530523 "meter-id": sq.meterID,
524 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400525 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700526 cir := meterInfo.MeterConfig.Bands[0].Rate
527 cbs := meterInfo.MeterConfig.Bands[0].BurstSize
528 eir := meterInfo.MeterConfig.Bands[1].Rate
529 ebs := meterInfo.MeterConfig.Bands[1].BurstSize
Manikkaraj kb1d51442019-07-23 10:41:02 -0400530 pir := cir + eir
531 pbs := cbs + ebs
532 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
533
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700534 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000535 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700537 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530538 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
539 log.Fields{"intf-id": sq.intfID,
540 "direction": sq.direction,
541 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400542 }
543
salmansiddiqui7ac62132019-08-22 03:58:50 +0000544 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400545 * store the meter id on the KV store, for further reference.
546 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700547 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530548 return olterrors.NewErrAdapter("failed-updating-meter-id",
549 log.Fields{"onu-id": sq.onuID,
550 "meter-id": sq.meterID,
551 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400552 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000553 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530554 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700555 "meter-info": meterInfo,
556 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400557 return nil
558}
559
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700560func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562
563 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530564 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
565 log.Fields{"intf-id": sq.intfID,
566 "direction": sq.direction,
567 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000568 }
569
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530571 log.Fields{
572 "direction": sq.direction,
573 "TrafficScheds": TrafficSched,
574 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530575 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576 IntfId: sq.intfID, OnuId: sq.onuID,
577 UniId: sq.uniID, PortNo: sq.uniPort,
578 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000579 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000580 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000581 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530582 "direction": sq.direction,
583 "traffic-queues": trafficQueues,
584 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000585
586 // On receiving the CreateTrafficQueues request, the driver should create corresponding
587 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000588 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530589 log.Fields{"direction": sq.direction,
590 "traffic-queues": trafficQueues,
591 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530592 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000593 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
594 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000595 TrafficQueues: trafficQueues,
596 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530597 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000598 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000599 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530600 "direction": sq.direction,
601 "traffic-queues": trafficQueues,
602 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000603
Esin Karamanccb714b2019-11-29 15:02:06 +0000604 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000605 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000606 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700607 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000608 //assumed that there is only one queue per PON for the multicast service
609 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
610 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000611 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000612 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700613 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000614 gemPortID: multicastQueuePerPonPort.GemportId,
615 servicePriority: multicastQueuePerPonPort.Priority,
616 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700617 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000618 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400619 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
620 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
621 return err
622 }
Shrey Baid26912972020-04-16 21:02:31 +0530623
Neha Sharma96b7bf22020-06-15 10:37:32 +0000624 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000625 }
626 }
627 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000628 return nil
629}
630
salmansiddiqui7ac62132019-08-22 03:58:50 +0000631// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530632func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633
634 var Direction string
635 var SchedCfg *tp_pb.SchedulerConfig
636 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000637 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530638 log.Fields{
639 "direction": sq.direction,
640 "intf-id": sq.intfID,
641 "onu-id": sq.onuID,
642 "uni-id": sq.uniID,
643 "uni-port": sq.uniPort,
644 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000645 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000646 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000648 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000649 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400650 Direction = "downstream"
651 }
652
Girish Kumar8f73fe02019-12-09 13:19:37 +0000653 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530654 return olterrors.NewErrNotFound("scheduler-config",
655 log.Fields{
656 "int-id": sq.intfID,
657 "direction": sq.direction,
658 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000659 }
660
Girish Gowdraa482f272021-03-24 23:04:19 -0700661 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400662
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700663 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000664 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000665
Neha Sharma96b7bf22020-06-15 10:37:32 +0000666 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000667 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530668 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
669 log.Fields{
670 "intf-id": sq.intfID,
671 "direction": sq.direction,
672 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000673 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400674
npujarec5762e2020-01-01 14:08:48 +0530675 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000676 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
677 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000678 TrafficQueues: TrafficQueues,
679 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000680 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530681 log.Fields{
682 "intf-id": sq.intfID,
683 "traffic-queues": TrafficQueues,
684 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000686 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530687 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000688 IntfId: sq.intfID, OnuId: sq.onuID,
689 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000691 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530692 log.Fields{
693 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700694 "traffic-schedulers": TrafficSched,
695 "onu-id": sq.onuID,
696 "uni-id": sq.uniID,
697 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400698 }
699
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700700 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
701 log.Fields{"device-id": f.deviceHandler.device.Id,
702 "intf-id": sq.intfID,
703 "onu-id": sq.onuID,
704 "uni-id": sq.uniID,
705 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000706
707 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400708 * delete the meter id on the KV store.
709 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700710 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530712 return olterrors.NewErrAdapter("unable-to-remove-meter",
713 log.Fields{
714 "onu": sq.onuID,
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{
Shrey Baid26912972020-04-16 21:02:31 +0530723 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700724 "device-id": f.deviceHandler.device.Id,
725 "intf-id": sq.intfID,
726 "onu-id": sq.onuID,
727 "uni-id": sq.uniID,
728 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400729 return err
730}
731
Gamze Abakafee36392019-10-03 11:17:24 +0000732// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700733func (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 +0000734 var allocIDs []uint32
735 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530736 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530737 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000738 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000739
npujarec5762e2020-01-01 14:08:48 +0530740 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
741 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000742 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530743
Neha Sharma96b7bf22020-06-15 10:37:32 +0000744 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530745 "intf-id": intfID,
746 "onu-id": onuID,
747 "uni-id": uniID,
748 "device-id": f.deviceHandler.device.Id,
749 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530750
Manikkaraj kb1d51442019-07-23 10:41:02 -0400751 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530752 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000753 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000754 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530755 log.Fields{
756 "path": tpPath,
757 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530758 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000759 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530760 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000761 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530762 log.Fields{
763 "error": err,
764 "tp-id": TpID,
765 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000766 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530767 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400768 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
769 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
770 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530771 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000772 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530773 log.Fields{
774 "uni": uni,
775 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530776 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530777 }
Gamze Abakafee36392019-10-03 11:17:24 +0000778
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700779 switch tpInst := techProfileInstance.(type) {
780 case *tp.TechProfile:
781 if UsMeterID != 0 {
782 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
783 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
784 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000785 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700786 log.Fields{
787 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700788 "onu-id": onuID,
789 "uni-id": uniID,
790 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700791 "meter-id": UsMeterID,
792 "device-id": f.deviceHandler.device.Id})
793 return 0, nil, nil
794 }
795 }
796 if DsMeterID != 0 {
797 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
798 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
799 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000800 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700801 log.Fields{
802 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700803 "onu-id": onuID,
804 "uni-id": uniID,
805 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700806 "meter-id": DsMeterID,
807 "device-id": f.deviceHandler.device.Id})
808 return 0, nil, nil
809 }
810 }
811 allocID := tpInst.UsScheduler.AllocID
812 for _, gem := range tpInst.UpstreamGemPortAttributeList {
813 gemPortIDs = append(gemPortIDs, gem.GemportID)
814 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700815 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000816
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700817 if tpInstanceExists {
818 return allocID, gemPortIDs, techProfileInstance
819 }
820
821 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700822 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700823 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000824 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700825 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700826 "intf-id": intfID,
827 "onu-id": onuID,
828 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700829 "alloc-ids": allocIDs,
830 "gemports": allgemPortIDs,
831 "device-id": f.deviceHandler.device.Id})
832 // Send Tconts and GEM ports to KV store
833 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530834 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700835 case *tp.EponProfile:
836 // CreateSchedulerQueues for EPON needs to be implemented here
837 // when voltha-protos for EPON is completed.
838 allocID := tpInst.AllocID
839 for _, gem := range tpInst.UpstreamQueueAttributeList {
840 gemPortIDs = append(gemPortIDs, gem.GemportID)
841 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700842 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843
844 if tpInstanceExists {
845 return allocID, gemPortIDs, techProfileInstance
846 }
847
848 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700849 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 log.Fields{
853 "alloc-ids": allocIDs,
854 "gemports": allgemPortIDs,
855 "device-id": f.deviceHandler.device.Id})
856 // Send Tconts and GEM ports to KV store
857 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
858 return allocID, gemPortIDs, techProfileInstance
859 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000860 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700861 log.Fields{
862 "tpInst": tpInst})
863 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530864 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530865}
866
npujarec5762e2020-01-01 14:08:48 +0530867func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530868
Neha Sharma96b7bf22020-06-15 10:37:32 +0000869 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530870 log.Fields{
871 "intf-id": intfID,
872 "onu-id": onuID,
873 "uni-id": uniID,
874 "alloc-id": allocID,
875 "gemport-ids": gemPortIDs,
876 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530877 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530878 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000879 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 +0530880 }
npujarec5762e2020-01-01 14:08:48 +0530881 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000882 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 +0530883 }
npujarec5762e2020-01-01 14:08:48 +0530884 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885 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 +0000886 } else {
887 //add to gem to uni cache
888 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530889 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000890 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 -0400891 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530892 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400893 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530894}
895
Esin Karamandf392e12020-12-16 13:33:09 +0000896//addGemPortUniAssociationsToCache
897func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
898 for _, gemPortID := range gemPortIDs {
899 key := gemPortKey{
900 intfID: intfID,
901 gemPort: gemPortID,
902 }
903 f.toGemToUniMap(ctx, key, onuID, uniID)
904 }
905 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
906 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
907}
908
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000910 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530911 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000912 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700913 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400914 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530916 log.Fields{
917 "intf-id": intfID,
918 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
920 }
921 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400922 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530923 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530924 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800925 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530926 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
927 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530928 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530930 log.Fields{
931 "numofTech": tpCount,
932 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
933 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530934 return nil
935}
936
Gamze Abaka7650be62021-02-26 10:50:36 +0000937func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
938 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000939 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530940 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000941 "uplinkClassifier": flowContext.classifier,
942 "uplinkAction": flowContext.action})
943 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530944 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Gamze Abaka7650be62021-02-26 10:50:36 +0000947func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
948 downlinkClassifier := flowContext.classifier
949 downlinkAction := flowContext.action
950
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700951 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
954 "downlinkClassifier": downlinkClassifier,
955 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400956 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
957 if vlan, exists := downlinkClassifier[VlanVid]; exists {
958 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700959 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000960 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530962 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000963 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530964 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000965 "onu-id": flowContext.onuID,
966 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400968 }
969 }
970 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530971 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400972
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400975 // vlan_vid is a uint32. must be type asserted as such or conversion fails
976 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530977 if ok {
978 downlinkAction[VlanVid] = dlClVid & 0xfff
979 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530980 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530981 "reason": "failed-to-convert-vlanid-classifier",
982 "vlan-id": VlanVid,
983 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530984 }
985
Gamze Abaka7650be62021-02-26 10:50:36 +0000986 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530987}
988
Gamze Abaka7650be62021-02-26 10:50:36 +0000989func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700990
991 var inverseDirection string
992 if direction == Upstream {
993 inverseDirection = Downstream
994 } else {
995 inverseDirection = Upstream
996 }
997
Gamze Abaka7650be62021-02-26 10:50:36 +0000998 intfID := flowContext.intfID
999 onuID := flowContext.onuID
1000 uniID := flowContext.uniID
1001 classifier := flowContext.classifier
1002 action := flowContext.action
1003 allocID := flowContext.allocID
1004 gemPortID := flowContext.gemPortID
1005 tpID := flowContext.tpID
1006 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001007 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301008 log.Fields{
1009 "intf-id": intfID,
1010 "onu-id": onuID,
1011 "uni-id": uniID,
1012 "device-id": f.deviceHandler.device.Id,
1013 "classifier": classifier,
1014 "action": action,
1015 "direction": direction,
1016 "alloc-id": allocID,
1017 "gemport-id": gemPortID,
1018 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001019
1020 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001021 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301022 log.Fields{
1023 "device-id": f.deviceHandler.device.Id,
1024 "intf-id": intfID,
1025 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001026 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301027 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 classifierProto, err := makeOpenOltClassifierField(classifier)
1029 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301030 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301031 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001032 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301033 log.Fields{
1034 "classifier": *classifierProto,
1035 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001036 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301038 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001040 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301041 log.Fields{
1042 "action": *actionProto,
1043 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001044 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301045 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301046 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001047 log.Fields{
1048 "classifier": classifier,
1049 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301050 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001051 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301052 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001053
1054 // Get symmetric flowID if it exists
1055 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1056 // symmetric flow earlier
1057 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1058 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1059 f.subscriberDataPathFlowIDMapLock.RLock()
1060 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1061 f.subscriberDataPathFlowIDMapLock.RUnlock()
1062
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001063 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001064 OnuId: int32(onuID),
1065 UniId: int32(uniID),
1066 FlowId: logicalFlow.Id,
1067 FlowType: direction,
1068 AllocId: int32(allocID),
1069 NetworkIntfId: int32(networkIntfID),
1070 GemportId: int32(gemPortID),
1071 Classifier: classifierProto,
1072 Action: actionProto,
1073 Priority: int32(logicalFlow.Priority),
1074 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001075 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001076 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001077 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1078 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001079 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001080 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001081 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001083 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301084 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001085 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301086 log.Fields{"direction": direction,
1087 "device-id": f.deviceHandler.device.Id,
1088 "flow": flow,
1089 "intf-id": intfID,
1090 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001091 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1092 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1093 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301094 log.Fields{
1095 "flow": flow,
1096 "device-id": f.deviceHandler.device.Id,
1097 "intf-id": intfID,
1098 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001100
1101 // Update the current flowID to the map
1102 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1103 f.subscriberDataPathFlowIDMapLock.Lock()
1104 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1105 f.subscriberDataPathFlowIDMapLock.Unlock()
1106
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301108}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001109
Gamze Abaka7650be62021-02-26 10:50:36 +00001110func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1111
1112 intfID := flowContext.intfID
1113 onuID := flowContext.onuID
1114 uniID := flowContext.uniID
1115 logicalFlow := flowContext.logicalFlow
1116 classifier := flowContext.classifier
1117 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301120 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301121 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001122 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301123 "action": action,
1124 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301126 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301127
1128 // Clear the action map
1129 for k := range action {
1130 delete(action, k)
1131 }
1132
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001133 action[TrapToHost] = true
1134 classifier[UDPSrc] = uint32(68)
1135 classifier[UDPDst] = uint32(67)
1136 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001138 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001139 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301140 log.Fields{
1141 "device-id": f.deviceHandler.device.Id,
1142 "intf-id": intfID,
1143 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
Neha Sharma96b7bf22020-06-15 10:37:32 +00001147 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301148 log.Fields{
1149 "ul_classifier": classifier,
1150 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001151 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301152 "intf-id": intfID,
1153 "onu-id": onuID,
1154 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 classifierProto, err := makeOpenOltClassifierField(classifier)
1157 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301158 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301159 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001160 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001161 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301163 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301164 }
1165
David K. Bainbridge794735f2020-02-11 21:01:37 -08001166 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001167 OnuId: int32(onuID),
1168 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001169 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001170 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001171 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001172 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001173 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301174 Classifier: classifierProto,
1175 Action: actionProto,
1176 Priority: int32(logicalFlow.Priority),
1177 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001178 PortNo: flowContext.portNo,
1179 TechProfileId: flowContext.tpID,
1180 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1181 PbitToGemport: flowContext.pbitToGem,
1182 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001183 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001184 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001185 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301188 log.Fields{
1189 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001190 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301191 "intf-id": intfID,
1192 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1194 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 +05301195 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1196 log.Fields{
1197 "flow": dhcpFlow,
1198 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199 }
1200
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301202}
1203
Esin Karamanae41e2b2019-12-17 18:13:13 +00001204//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001205func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1206 delete(flowContext.classifier, VlanVid)
1207 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001208}
1209
1210//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001211func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1212
1213 intfID := flowContext.intfID
1214 onuID := flowContext.onuID
1215 uniID := flowContext.uniID
1216 logicalFlow := flowContext.logicalFlow
1217 classifier := flowContext.classifier
1218 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219
Neha Sharma96b7bf22020-06-15 10:37:32 +00001220 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301222 return olterrors.NewErrNotFound("nni-interface-id",
1223 log.Fields{
1224 "classifier": classifier,
1225 "action": action,
1226 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001227 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001228 }
1229
1230 // Clear the action map
1231 for k := range action {
1232 delete(action, k)
1233 }
1234
1235 action[TrapToHost] = true
1236 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001238 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001239 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001240 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241 }
1242
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301244 log.Fields{
1245 "ul_classifier": classifier,
1246 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001247 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301248 "device-id": f.deviceHandler.device.Id,
1249 "intf-id": intfID,
1250 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 classifierProto, err := makeOpenOltClassifierField(classifier)
1253 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301254 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001256 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301257 log.Fields{
1258 "classifier": *classifierProto,
1259 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001260 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001261 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301262 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266 OnuId: int32(onuID),
1267 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001268 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001270 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001271 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001272 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273 Classifier: classifierProto,
1274 Action: actionProto,
1275 Priority: int32(logicalFlow.Priority),
1276 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001277 PortNo: flowContext.portNo,
1278 TechProfileId: flowContext.tpID,
1279 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1280 PbitToGemport: flowContext.pbitToGem,
1281 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001282 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001285 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 -08001286 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001288 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1289 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 +05301290 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 +00001291 }
1292
David K. Bainbridge794735f2020-02-11 21:01:37 -08001293 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001294}
1295
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001296// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001297func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1298 intfID := flowContext.intfID
1299 onuID := flowContext.onuID
1300 uniID := flowContext.uniID
1301 portNo := flowContext.portNo
1302 allocID := flowContext.allocID
1303 gemPortID := flowContext.gemPortID
1304 logicalFlow := flowContext.logicalFlow
1305 classifier := flowContext.classifier
1306 action := flowContext.action
1307
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001308 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301309 log.Fields{
1310 "intf-id": intfID,
1311 "onu-id": onuID,
1312 "port-no": portNo,
1313 "alloc-id": allocID,
1314 "gemport-id": gemPortID,
1315 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001316 "flow": logicalFlow,
1317 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301318
1319 uplinkClassifier := make(map[string]interface{})
1320 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301321
manikkaraj kbf256be2019-03-25 00:13:48 +05301322 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001323 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001324 uplinkClassifier[PacketTagType] = SingleTag
1325 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001326 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301327 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001329 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001330 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301331 "device-id": f.deviceHandler.device.Id,
1332 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "intf-id": intfID,
1334 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001335 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301336 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001337 //Add Uplink EthType Flow
1338 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301339 log.Fields{
1340 "ul_classifier": uplinkClassifier,
1341 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001342 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301343 "device-id": f.deviceHandler.device.Id,
1344 "intf-id": intfID,
1345 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301346
David K. Bainbridge794735f2020-02-11 21:01:37 -08001347 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1348 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301349 return olterrors.NewErrInvalidValue(log.Fields{
1350 "classifier": uplinkClassifier,
1351 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301352 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001353 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301354 log.Fields{
1355 "classifier": *classifierProto,
1356 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001357 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001358 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301359 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001361 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301362 log.Fields{
1363 "action": *actionProto,
1364 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001365 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301366 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301367 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301369 "action": action,
1370 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001371 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301372 }
1373
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 OnuId: int32(onuID),
1376 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001377 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001378 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001379 AllocId: int32(allocID),
1380 NetworkIntfId: int32(networkIntfID),
1381 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 Classifier: classifierProto,
1383 Action: actionProto,
1384 Priority: int32(logicalFlow.Priority),
1385 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001386 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001387 TechProfileId: flowContext.tpID,
1388 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1389 PbitToGemport: flowContext.pbitToGem,
1390 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001391 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001392 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001393 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001394 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001395 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301396 log.Fields{
1397 "device-id": f.deviceHandler.device.Id,
1398 "onu-id": onuID,
1399 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001400 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301401 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001402 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1403 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 +05301404 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1405 log.Fields{
1406 "flow": upstreamFlow,
1407 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301408 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301410}
1411
David K. Bainbridge794735f2020-02-11 21:01:37 -08001412func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414
1415 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1416 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1417 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001418 if vlanID != ReservedVlan {
1419 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001420 classifier.OVid = vid
1421 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001423 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1424 vid := uint32(metadata)
1425 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001426 classifier.IVid = vid
1427 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301428 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301429 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301431 classifier.OPbits = vlanPcp
1432 } else {
1433 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301434 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001435 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1436 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1437 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1438 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001439 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001440 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1441 classifier.PktTagType = pktTagType
1442
1443 switch pktTagType {
1444 case SingleTag:
1445 case DoubleTag:
1446 case Untagged:
1447 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001448 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301449 }
1450 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001451 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301452}
1453
Gamze Abaka724d0852020-03-18 12:10:24 +00001454func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001455 var actionCmd openoltpb2.ActionCmd
1456 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301457 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001458 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301459 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001460 if _, ok := actionInfo[VlanPcp]; ok {
1461 action.Cmd.RemarkInnerPbits = true
1462 action.IPbits = actionInfo[VlanPcp].(uint32)
1463 if _, ok := actionInfo[VlanVid]; ok {
1464 action.Cmd.TranslateInnerTag = true
1465 action.IVid = actionInfo[VlanVid].(uint32)
1466 }
1467 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001468 } else if _, ok := actionInfo[PushVlan]; ok {
1469 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301470 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001471 if _, ok := actionInfo[VlanPcp]; ok {
1472 action.OPbits = actionInfo[VlanPcp].(uint32)
1473 action.Cmd.RemarkOuterPbits = true
1474 if _, ok := classifierInfo[VlanVid]; ok {
1475 action.IVid = classifierInfo[VlanVid].(uint32)
1476 action.Cmd.TranslateInnerTag = true
1477 }
1478 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001479 } else if _, ok := actionInfo[TrapToHost]; ok {
1480 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301481 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001482 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001484 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301485}
1486
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001487// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001488func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1489 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301490}
1491
Gamze Abakafee36392019-10-03 11:17:24 +00001492// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001493func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301494 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001495 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1496
Gamze Abakafee36392019-10-03 11:17:24 +00001497 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301498 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001499 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301500 // return err
1501 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001502 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001503 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001504 }
1505 return nil
1506}
1507
1508// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301509func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001510 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001511 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001512 }
npujarec5762e2020-01-01 14:08:48 +05301513 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301514 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1515 log.Fields{
1516 "tp-id": tpID,
1517 "uni-port-name": uniPortName,
1518 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001519 }
1520 return nil
1521}
1522
David K. Bainbridge794735f2020-02-11 21:01:37 -08001523func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001524
1525 var intfID uint32
1526 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1527 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1528 */
1529 if deviceFlow.AccessIntfId != -1 {
1530 intfID = uint32(deviceFlow.AccessIntfId)
1531 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001532 // We need to log the valid interface ID.
1533 // 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 +00001534 intfID = uint32(deviceFlow.NetworkIntfId)
1535 }
1536
Neha Sharma96b7bf22020-06-15 10:37:32 +00001537 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301538 "flow": *deviceFlow,
1539 "device-id": f.deviceHandler.device.Id,
1540 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001541 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001542
1543 st, _ := status.FromError(err)
1544 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001546 "err": err,
1547 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301548 "device-id": f.deviceHandler.device.Id,
1549 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301551 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001552
1553 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301555 log.Fields{"err": err,
1556 "device-flow": deviceFlow,
1557 "device-id": f.deviceHandler.device.Id,
1558 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301562 log.Fields{
1563 "flow": *deviceFlow,
1564 "device-id": f.deviceHandler.device.Id,
1565 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001566
1567 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1568 if deviceFlow.AccessIntfId != -1 {
1569 // No need to register the flow if it is a trap on nni flow.
1570 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1571 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1572 return err
1573 }
1574 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001576}
1577
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1579 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301580 log.Fields{
1581 "flow": *deviceFlow,
1582 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001583 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001584 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001585 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301587 log.Fields{
1588 "err": err,
1589 "deviceFlow": deviceFlow,
1590 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001591 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001592 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001593 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001594 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001595
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001596 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001598 "of-flow-id": ofFlowID,
1599 "flow": *deviceFlow,
1600 "device-id": f.deviceHandler.device.Id,
1601 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301603}
1604
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001606
1607 classifierInfo := make(map[string]interface{})
1608 actionInfo := make(map[string]interface{})
1609
1610 classifierInfo[EthType] = uint32(LldpEthType)
1611 classifierInfo[PacketTagType] = Untagged
1612 actionInfo[TrapToHost] = true
1613
1614 // LLDP flow is installed to trap LLDP packets on the NNI port.
1615 // We manage flow_id resource pool on per PON port basis.
1616 // Since this situation is tricky, as a hack, we pass the NNI port
1617 // index (network_intf_id) as PON port Index for the flow_id resource
1618 // pool. Also, there is no ONU Id available for trapping LLDP packets
1619 // on NNI port, use onu_id as -1 (invalid)
1620 // ****************** CAVEAT *******************
1621 // This logic works if the NNI Port Id falls within the same valid
1622 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1623 // we need to have a re-look at this.
1624 // *********************************************
1625
1626 var onuID = -1
1627 var uniID = -1
1628 var gemPortID = -1
1629
Neha Sharma96b7bf22020-06-15 10:37:32 +00001630 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301632 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001633 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001634 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001637 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001638
David K. Bainbridge794735f2020-02-11 21:01:37 -08001639 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1640 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301641 return olterrors.NewErrInvalidValue(
1642 log.Fields{
1643 "classifier": classifierInfo,
1644 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001645 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301647 log.Fields{
1648 "classifier": *classifierProto,
1649 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001650 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001651 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301652 return olterrors.NewErrInvalidValue(
1653 log.Fields{
1654 "action": actionInfo,
1655 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001656 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001657 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301658 log.Fields{
1659 "action": *actionProto,
1660 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001661
1662 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1663 OnuId: int32(onuID), // OnuId not required
1664 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001665 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001666 FlowType: Downstream,
1667 NetworkIntfId: int32(networkInterfaceID),
1668 GemportId: int32(gemPortID),
1669 Classifier: classifierProto,
1670 Action: actionProto,
1671 Priority: int32(flow.Priority),
1672 Cookie: flow.Cookie,
1673 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001674 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301676 log.Fields{
1677 "flow": downstreamflow,
1678 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301681 log.Fields{
1682 "device-id": f.deviceHandler.device.Id,
1683 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001684 "flow-id": flow.Id})
1685 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1686 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1687 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301688 log.Fields{
1689 "flow": downstreamflow,
1690 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 }
1692 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301693}
1694
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001695func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1696 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001697}
1698
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001699//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001701 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1702 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1703 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001704 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301705 log.Fields{
1706 "intf-id": intfID,
1707 "onu-id": onuID,
1708 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001710 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301711 return nil, olterrors.NewErrNotFound("onu-child-device",
1712 log.Fields{
1713 "onu-id": onuID,
1714 "intf-id": intfID,
1715 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001716 }
1717 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1718 //better to ad the device to cache here.
1719 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1720 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301722 log.Fields{
1723 "intf-id": intfID,
1724 "onu-id": onuID,
1725 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001726 }
1727
1728 return onuDev.(*OnuDevice), nil
1729}
1730
1731//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001732func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1733 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301734 log.Fields{
1735 "pon-port": intfID,
1736 "onu-id": onuID,
1737 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001738 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001740 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301741 return nil, olterrors.NewErrNotFound("onu",
1742 log.Fields{
1743 "interface-id": parentPortNo,
1744 "onu-id": onuID,
1745 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001746 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301747 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301749 log.Fields{
1750 "device-id": f.deviceHandler.device.Id,
1751 "child_device_id": onuDevice.Id,
1752 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301753 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301754}
1755
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1757 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301758 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001759 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301760 log.Fields{
1761 "intf-id": intfID,
1762 "onu-id": onuID,
1763 "uni-id": uniID,
1764 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001765 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301766 }
1767
1768 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
1771 "msg": *delGemPortMsg,
1772 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001773 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301774 delGemPortMsg,
1775 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001776 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001777 onuDev.deviceType,
1778 onuDev.deviceID,
1779 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301780 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1781 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001782 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301783 "to-adapter": onuDev.deviceType,
1784 "onu-id": onuDev.deviceID,
1785 "proxyDeviceID": onuDev.proxyDeviceID,
1786 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301787 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301789 log.Fields{
1790 "msg": delGemPortMsg,
1791 "from-adapter": f.deviceHandler.device.Type,
1792 "to-adapter": onuDev.deviceType,
1793 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301794 return nil
1795}
1796
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1798 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301799 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301801 log.Fields{
1802 "intf-id": intfID,
1803 "onu-id": onuID,
1804 "uni-id": uniID,
1805 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001806 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301807 }
1808
1809 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001810 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301811 log.Fields{
1812 "msg": *delTcontMsg,
1813 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001814 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301815 delTcontMsg,
1816 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001817 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001818 onuDev.deviceType,
1819 onuDev.deviceID,
1820 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301821 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1822 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001823 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301824 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1825 "proxyDeviceID": onuDev.proxyDeviceID,
1826 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301827 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001828 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301829 log.Fields{
1830 "msg": delTcontMsg,
1831 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301832 return nil
1833}
1834
Girish Gowdrac3037402020-01-22 20:29:53 +05301835// Once the gemport is released for a given onu, it also has to be cleared from local cache
1836// which was used for deriving the gemport->logicalPortNo during packet-in.
1837// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1838// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001839func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001840
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001841 f.onuGemInfoLock.Lock()
1842 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001843
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301845 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001846 "gem-port-id": gemPortID,
1847 "intf-id": intfID,
1848 "onu-id": onuID,
1849 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001850 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001851
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001852 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001853deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001854 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301855 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001856 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301857 // If the gemport is found, delete it from local cache.
1858 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001859 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1860 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
1863 "intf-id": intfID,
1864 "onu-id": onuID,
1865 "deletedgemport-id": gemPortID,
1866 "gemports": onu.GemPorts,
1867 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001868 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301869 }
1870 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001871 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301872 }
1873 }
1874}
1875
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301876//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001877// nolint: gocyclo
Girish Gowdraa482f272021-03-24 23:04:19 -07001878func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001879 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001880
Girish Gowdraa482f272021-03-24 23:04:19 -07001881 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1882 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001883 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1884 log.Fields{
1885 "tpPath": tpPath,
1886 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001887 techprofileInst, err := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001888 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1889 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1890 log.Fields{
1891 "tp-id": tpID,
1892 "path": tpPath}, err)
1893 }
1894
1895 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1896
1897 if used {
1898 f.flowsUsedByGemPortKey.Lock()
1899 defer f.flowsUsedByGemPortKey.Unlock()
1900
1901 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1902 for i, flowIDinMap := range flowIDs {
1903 if flowIDinMap == flowID {
1904 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1905 // everytime flowsUsedByGemPort cache is updated the same should be updated
1906 // in kv store by calling UpdateFlowIDsForGem
1907 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
Girish Gowdraa482f272021-03-24 23:04:19 -07001908 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001909 return err
1910 }
1911 break
1912 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001913 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001914 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1915 log.Fields{
1916 "gemport-id": gemPortID,
1917 "usedByFlows": flowIDs,
1918 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001919
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 return nil
1921 }
1922 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001923 f.resourceMgr.RemoveGemPortIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001924 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1925 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Girish Gowdraa482f272021-03-24 23:04:19 -07001926 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), intfID)
Esin Karamandf392e12020-12-16 13:33:09 +00001927 // also clear gem to uni cache
1928 f.removeFromGemToUniMap(gemPortKey{
Girish Gowdraa482f272021-03-24 23:04:19 -07001929 intfID: intfID,
Esin Karamandf392e12020-12-16 13:33:09 +00001930 gemPort: uint32(gemPortID),
1931 })
Girish Gowdraa482f272021-03-24 23:04:19 -07001932 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001933
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934 f.onuIdsLock.Lock() // TODO: What is this lock?
1935
1936 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1937 // by calling DeleteFlowIDsForGem
1938 f.flowsUsedByGemPortKey.Lock()
1939 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1940 f.flowsUsedByGemPortKey.Unlock()
Girish Gowdraa482f272021-03-24 23:04:19 -07001941 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1942 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943
1944 f.onuIdsLock.Unlock()
1945
1946 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001947 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001948 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1949 log.Fields{
1950 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001951 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001952 "onu-id": onuID,
1953 "uni-id": uniID,
1954 "device-id": f.deviceHandler.device.Id,
1955 "gemport-id": gemPortID})
1956 }
1957 switch techprofileInst := techprofileInst.(type) {
1958 case *tp.TechProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001959 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001960 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001961 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 logger.Warn(ctx, err)
1963 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001964 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001965 logger.Warn(ctx, err)
1966 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001967 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001968 logger.Warn(ctx, err)
1969 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001970 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971 logger.Warn(ctx, err)
1972 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001973 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001975 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1977 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001978 "intf": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 "onu-id": onuID,
1980 "uni-id": uniID,
1981 "device-id": f.deviceHandler.device.Id,
1982 "alloc-id": techprofileInst.UsScheduler.AllocID})
1983 }
1984 }
1985 case *tp.EponProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001986 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987 logger.Warn(ctx, err)
1988 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001989 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 logger.Warn(ctx, err)
1991 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001992 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001993 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001994 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001995 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301996 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001997 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301998 "onu-id": onuID,
1999 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002000 "device-id": f.deviceHandler.device.Id,
2001 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00002002 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002003 default:
2004 logger.Errorw(ctx, "error-unknown-tech",
2005 log.Fields{
2006 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002007 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002008
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302009 return nil
2010}
2011
David K. Bainbridge794735f2020-02-11 21:01:37 -08002012// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002013func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002014 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002015 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302016 log.Fields{
2017 "flowDirection": flowDirection,
2018 "flow": *flow,
2019 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002020
2021 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002022 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002023 }
2024
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302025 classifierInfo := make(map[string]interface{})
2026
Neha Sharma96b7bf22020-06-15 10:37:32 +00002027 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302028 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002030 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302031 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302032
David K. Bainbridge794735f2020-02-11 21:01:37 -08002033 onuID := int32(onu)
2034 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302035
2036 for _, field := range flows.GetOfbFields(flow) {
2037 if field.Type == flows.IP_PROTO {
2038 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302040 }
2041 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302043 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002044 "flow-id": flow.Id,
2045 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302046 "onu-id": onuID,
2047 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302048
2049 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2050 onuID = -1
2051 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002052 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2053 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002054 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002055 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002056 log.Fields{
2057 "port-number": inPort,
2058 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002059 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302061 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002062 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2063 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})
2064 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2065 }
2066 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2067 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2068 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2069 return err
2070 }
2071 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2072 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2073 return err
2074 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002075 tpID, err := getTpIDFromFlow(ctx, flow)
2076 if err != nil {
2077 return olterrors.NewErrNotFound("tp-id",
2078 log.Fields{
2079 "flow": flow,
2080 "intf-id": Intf,
2081 "onu-id": onuID,
2082 "uni-id": uniID,
2083 "device-id": f.deviceHandler.device.Id}, err)
2084 }
2085
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 if !flowInfo.Flow.ReplicateFlow {
Girish Gowdra82c80982021-03-26 16:22:02 -07002087 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002088 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002089 "flow-id": flow.Id,
2090 "stored-flow": flowInfo.Flow,
2091 "device-id": f.deviceHandler.device.Id,
2092 "stored-flow-id": flowInfo.Flow.FlowId,
2093 "onu-id": onuID,
2094 "intf": Intf,
Girish Gowdra82c80982021-03-26 16:22:02 -07002095 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002096 })
2097 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302098 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002099 } else {
2100 gems := make([]uint32, 0)
2101 for _, gem := range flowInfo.Flow.PbitToGemport {
2102 gems = appendUnique32bit(gems, gem)
2103 }
2104 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2105 for _, gem := range gems {
Girish Gowdra82c80982021-03-26 16:22:02 -07002106 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002107 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002108 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002109 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002110 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002111 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002112 "onu-id": onuID,
2113 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002114 "gem": gem,
Girish Gowdra82c80982021-03-26 16:22:02 -07002115 "err": err,
Matteo Scandolo92186242020-06-12 10:54:18 -07002116 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002117 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302118 }
2119 }
2120 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002121
2122 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2123 if isDatapathFlow(flow) {
2124 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2125 var inverseDirection string
2126 if flowDirection == Upstream {
2127 inverseDirection = Downstream
2128 } else {
2129 inverseDirection = Upstream
2130 }
2131
2132 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002133 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002134 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002135 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002136 }
2137 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002138 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2139 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2140 return err
2141 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002142 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002143}
2144
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002145//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002146func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002147
Neha Sharma96b7bf22020-06-15 10:37:32 +00002148 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302149 var direction string
2150 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002151
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302152 for _, action := range flows.GetActions(flow) {
2153 if action.Type == flows.OUTPUT {
2154 if out := action.GetOutput(); out != nil {
2155 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002156 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302157 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002159 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002160 }
2161 }
2162 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002163
2164 if flows.HasGroup(flow) {
2165 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002166 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002167 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302168 direction = Upstream
2169 } else {
2170 direction = Downstream
2171 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302172
Girish Gowdracefae192020-03-19 18:14:10 -07002173 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002174 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002175
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002176 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002177}
2178
Esin Karamanae41e2b2019-12-17 18:13:13 +00002179//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2180func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2181 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2182 if ethType, ok := classifierInfo[EthType]; ok {
2183 if ethType.(uint32) == IPv4EthType {
2184 if ipProto, ok := classifierInfo[IPProto]; ok {
2185 if ipProto.(uint32) == IgmpProto {
2186 return true
2187 }
2188 }
2189 }
2190 }
2191 }
2192 return false
2193}
2194
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002195// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2196func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2197 // Step1 : Fill flowControlBlock
2198 // Step2 : Push the flowControlBlock to ONU channel
2199 // Step3 : Wait on response channel for response
2200 // Step4 : Return error value
2201 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2202 errChan := make(chan error)
2203 flowCb := flowControlBlock{
2204 ctx: ctx,
2205 addFlow: addFlow,
2206 flow: flow,
2207 flowMetadata: flowMetadata,
2208 errChan: &errChan,
2209 }
2210 inPort, outPort := getPorts(flow)
2211 var onuID uint32
2212 if inPort != InvalidPort && outPort != InvalidPort {
2213 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2214 }
2215 // inPort or outPort is InvalidPort for trap-from-nni flows.
2216 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2217 // Send the flowCb on the ONU flow channel
2218 f.incomingFlows[onuID] <- flowCb
2219 // Wait on the channel for flow handlers return value
2220 err := <-errChan
2221 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2222 return err
2223}
2224
2225// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2226// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2227func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2228 for {
2229 // block on the channel to receive an incoming flow
2230 // process the flow completely before proceeding to handle the next flow
2231 flowCb := <-subscriberFlowChannel
2232 if flowCb.addFlow {
2233 logger.Debugw(flowCb.ctx, "adding-flow",
2234 log.Fields{"device-id": f.deviceHandler.device.Id,
2235 "flowToAdd": flowCb.flow})
2236 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2237 // Pass the return value over the return channel
2238 *flowCb.errChan <- err
2239 } else {
2240 logger.Debugw(flowCb.ctx, "removing-flow",
2241 log.Fields{"device-id": f.deviceHandler.device.Id,
2242 "flowToRemove": flowCb.flow})
2243 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2244 // Pass the return value over the return channel
2245 *flowCb.errChan <- err
2246 }
2247 }
2248}
2249
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002250// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302251// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002252func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002253 classifierInfo := make(map[string]interface{})
2254 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002255 var UsMeterID uint32
2256 var DsMeterID uint32
2257
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302259 log.Fields{
2260 "flow": flow,
2261 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002262 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002263
Neha Sharma96b7bf22020-06-15 10:37:32 +00002264 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002265 if err != nil {
2266 // Error logging is already done in the called function
2267 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002268 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302269 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002270
Esin Karamanccb714b2019-11-29 15:02:06 +00002271 if flows.HasGroup(flow) {
2272 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002273 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002274 }
2275
manikkaraj k17652a72019-05-06 09:06:36 -04002276 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002277 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002278 if err != nil {
2279 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002280 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002281 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002282
Neha Sharma96b7bf22020-06-15 10:37:32 +00002283 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302284 log.Fields{
2285 "classifierinfo_inport": classifierInfo[InPort],
2286 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002287 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002288
Humera Kouser94d7a842019-08-25 19:04:32 -04002289 if ethType, ok := classifierInfo[EthType]; ok {
2290 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002292 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002293 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002294 if ethType.(uint32) == PPPoEDEthType {
2295 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2296 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2297 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2298 }
2299 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002300 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002301 if ipProto, ok := classifierInfo[IPProto]; ok {
2302 if ipProto.(uint32) == IPProtoDhcp {
2303 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302304 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002305 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002306 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002307 }
2308 }
2309 }
2310 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002311 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002313 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002314 }
A R Karthick1f85b802019-10-11 05:06:05 +00002315
npujarec5762e2020-01-01 14:08:48 +05302316 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002317
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002319 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302320 return olterrors.NewErrNotFound("tpid-for-flow",
2321 log.Fields{
2322 "flow": flow,
2323 "intf-id": IntfID,
2324 "onu-id": onuID,
2325 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302328 log.Fields{
2329 "tp-id": TpID,
2330 "intf-id": intfID,
2331 "onu-id": onuID,
2332 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002333 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002334 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002336 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002337 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002339
2340 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002341 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002342}
Girish Gowdra3d633032019-12-10 16:37:05 +05302343
Esin Karamanccb714b2019-11-29 15:02:06 +00002344// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002345func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002346 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302348 "classifier-info": classifierInfo,
2349 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002350
Esin Karaman65409d82020-03-18 10:58:18 +00002351 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002352 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002353 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002354 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002355
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002356 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002357
David K. Bainbridge794735f2020-02-11 21:01:37 -08002358 onuID := NoneOnuID
2359 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002360
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002361 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002363 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002365 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2366 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002367 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 }
2369 groupID := actionInfo[GroupID].(uint32)
2370 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002371 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002372 FlowType: Multicast,
2373 NetworkIntfId: int32(networkInterfaceID),
2374 GroupId: groupID,
2375 Classifier: classifierProto,
2376 Priority: int32(flow.Priority),
2377 Cookie: flow.Cookie}
2378
Kent Hagermane6ff1012020-07-14 15:07:53 -04002379 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002380 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002381 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002382 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002383 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002384 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002385 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002386 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002387 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002388 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002389 //cached group can be removed now
2390 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2391 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2392 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002393 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002394
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002395 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2396 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2397 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002398 }
2399 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002400}
2401
Esin Karaman65409d82020-03-18 10:58:18 +00002402//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2403func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2404 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002406 if err != nil {
2407 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2408 }
2409 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002410 }
Esin Karaman65409d82020-03-18 10:58:18 +00002411 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302412 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002413 if e == nil && len(nniPorts) > 0 {
2414 return nniPorts[0], nil
2415 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302416 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002417}
2418
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002419//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002421
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302423 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302425 log.Fields{
2426 "intf-id": intfID,
2427 "onu-id": onuID,
2428 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002429 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302430 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002431 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002432
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002434 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002435 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002436 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002437 tpDownloadMsg,
2438 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002439 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002440 onuDev.deviceType,
2441 onuDev.deviceID,
2442 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002443 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302444 return olterrors.NewErrCommunication("send-techprofile-download-request",
2445 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002446 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302447 "to-adapter": onuDev.deviceType,
2448 "onu-id": onuDev.deviceID,
2449 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002450 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002451 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302452 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302453}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002454
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302455//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002456func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302457
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002458 f.onuGemInfoLock.Lock()
2459 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002460 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002461 // If the ONU already exists in onuGemInfo list, nothing to do
2462 for _, onu := range onugem {
2463 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2464 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2465 log.Fields{"onuID": onuID,
2466 "serialNum": serialNum})
2467 return nil
2468 }
2469 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002470
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302471 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002472 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002473 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002474 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302477 log.Fields{
2478 "intf-id": intfID,
2479 "onu-id": onuID,
2480 "serial-num": serialNum,
2481 "onu": onu,
2482 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002483 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002484}
2485
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302486//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302487func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002488
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002489 f.onuGemInfoLock.Lock()
2490 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002491
Neha Sharma96b7bf22020-06-15 10:37:32 +00002492 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302493 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002494 "gem-port-id": gemPort,
2495 "intf-id": intfID,
2496 "onu-id": onuID,
2497 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002498 "onu-gem": f.onuGemInfo})
2499 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302500 // update the gem to the local cache as well as to kv strore
2501 for idx, onu := range onugem {
2502 if onu.OnuID == onuID {
2503 // check if gem already exists , else update the cache and kvstore
2504 for _, gem := range onu.GemPorts {
2505 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002506 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302507 log.Fields{
2508 "gem": gemPort,
2509 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302510 return
2511 }
2512 }
2513 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002514 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002515 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302516 }
2517 }
npujarec5762e2020-01-01 14:08:48 +05302518 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302519 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002520 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302521 log.Fields{
2522 "intf-id": intfID,
2523 "onu-id": onuID,
2524 "gemPort": gemPort,
2525 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002526 return
2527 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002528 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302529 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002530 "gem-port-id": gemPort,
2531 "intf-id": intfID,
2532 "onu-id": onuID,
2533 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002534 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002535}
2536
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002537//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302538func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002539 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002540 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002541 var err error
2542
2543 if packetIn.IntfType == "pon" {
2544 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002545 // get onu and uni ids associated with the given pon and gem ports
2546 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002547 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 return logicalPortNum, err
2549 }
Esin Karamandf392e12020-12-16 13:33:09 +00002550 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2551
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 if packetIn.PortNo != 0 {
2553 logicalPortNum = packetIn.PortNo
2554 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002556 }
2557 // 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 +00002558 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002559 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002560 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002561 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002562
2563 if logger.V(log.DebugLevel) {
2564 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2565 log.Fields{
2566 "logical-port-num": logicalPortNum,
2567 "intf-type": packetIn.IntfType,
2568 "packet": hex.EncodeToString(packetIn.Pkt),
2569 })
2570 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002571 return logicalPortNum, nil
2572}
2573
Esin Karamandf392e12020-12-16 13:33:09 +00002574//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2575func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2576 key := gemPortKey{
2577 intfID: intfID,
2578 gemPort: gemPortID,
2579 }
2580 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2581 if ok {
2582 if len(uniPortInfo) > 1 {
2583 //return onu ID and uni port from the cache
2584 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2585 log.Fields{
2586 "intfID": intfID,
2587 "gemPortID": gemPortID,
2588 "onuID, uniID": uniPortInfo})
2589 return uniPortInfo[0], uniPortInfo[1], nil
2590 }
2591 }
2592 //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.
2593 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2594 if err == nil {
2595 f.toGemToUniMap(ctx, key, onuID, uniID)
2596 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2597 log.Fields{
2598 "gemPortKey": key,
2599 "onuID": onuID,
2600 "uniID": uniID})
2601 return onuID, uniID, nil
2602 }
2603 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2604 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2605 errors.New("no uni port found"))
2606}
2607
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002608//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002609func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002610 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002611
2612 ctag, priority, err := getCTagFromPacket(ctx, packet)
2613 if err != nil {
2614 return 0, err
2615 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302616
Esin Karaman7fb80c22020-07-16 14:23:33 +00002617 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002618 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002619 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002620 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002621 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302622 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002623 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302624 log.Fields{
2625 "pktinkey": pktInkey,
2626 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002627
2628 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002629 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302630 //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 +00002631 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 if err == nil {
2633 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002634 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302635 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002636 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302638 log.Fields{
2639 "pktinkey": pktInkey,
2640 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302641 return gemPortID, nil
2642 }
2643 }
Shrey Baid26912972020-04-16 21:02:31 +05302644 return uint32(0), olterrors.NewErrNotFound("gem-port",
2645 log.Fields{
2646 "pktinkey": pktInkey,
2647 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002648
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649}
2650
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002651func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2652 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002654 classifier[PacketTagType] = DoubleTag
2655 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656 /* We manage flowId resource pool on per PON port basis.
2657 Since this situation is tricky, as a hack, we pass the NNI port
2658 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002659 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002660 on NNI port, use onu_id as -1 (invalid)
2661 ****************** CAVEAT *******************
2662 This logic works if the NNI Port Id falls within the same valid
2663 range of PON Port Ids. If this doesn't work for some OLT Vendor
2664 we need to have a re-look at this.
2665 *********************************************
2666 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002667 onuID := -1
2668 uniID := -1
2669 gemPortID := -1
2670 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302673 return olterrors.NewErrNotFound("nni-intreface-id",
2674 log.Fields{
2675 "classifier": classifier,
2676 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002677 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302678 }
2679
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002682 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002683 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002684
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002685 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2686 log.Fields{
2687 "classifier": classifier,
2688 "action": action,
2689 "flowId": logicalFlow.Id,
2690 "intf-id": networkInterfaceID})
2691
David K. Bainbridge794735f2020-02-11 21:01:37 -08002692 classifierProto, err := makeOpenOltClassifierField(classifier)
2693 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002694 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002696 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002697 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002698 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002699 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002701 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002702 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2703 OnuId: int32(onuID), // OnuId not required
2704 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002705 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002706 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002707 AllocId: int32(allocID), // AllocId not used
2708 NetworkIntfId: int32(networkInterfaceID),
2709 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 Classifier: classifierProto,
2711 Action: actionProto,
2712 Priority: int32(logicalFlow.Priority),
2713 Cookie: logicalFlow.Cookie,
2714 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002715 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002716 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002717 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002718 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002719 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2720 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2721 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002722 }
2723 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002724}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002725
Esin Karamanae41e2b2019-12-17 18:13:13 +00002726//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2727func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2728 var packetType string
2729 ovid, ivid := false, false
2730 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2731 vid := vlanID & VlanvIDMask
2732 if vid != ReservedVlan {
2733 ovid = true
2734 }
2735 }
2736 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2737 vid := uint32(metadata)
2738 if vid != ReservedVlan {
2739 ivid = true
2740 }
2741 }
2742 if ovid && ivid {
2743 packetType = DoubleTag
2744 } else if !ovid && !ivid {
2745 packetType = Untagged
2746 } else {
2747 packetType = SingleTag
2748 }
2749 return packetType
2750}
2751
2752//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002753func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002754 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002755 action := make(map[string]interface{})
2756 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2757 action[TrapToHost] = true
2758 /* We manage flowId resource pool on per PON port basis.
2759 Since this situation is tricky, as a hack, we pass the NNI port
2760 index (network_intf_id) as PON port Index for the flowId resource
2761 pool. Also, there is no ONU Id available for trapping packets
2762 on NNI port, use onu_id as -1 (invalid)
2763 ****************** CAVEAT *******************
2764 This logic works if the NNI Port Id falls within the same valid
2765 range of PON Port Ids. If this doesn't work for some OLT Vendor
2766 we need to have a re-look at this.
2767 *********************************************
2768 */
2769 onuID := -1
2770 uniID := -1
2771 gemPortID := -1
2772 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002773 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002774 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302775 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002776 "classifier": classifier,
2777 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002778 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002780 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002781 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002783 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002784
David K. Bainbridge794735f2020-02-11 21:01:37 -08002785 classifierProto, err := makeOpenOltClassifierField(classifier)
2786 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002787 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002789 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002790 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002791 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002792 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002793 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002795 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2796 OnuId: int32(onuID), // OnuId not required
2797 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002799 FlowType: Downstream,
2800 AllocId: int32(allocID), // AllocId not used
2801 NetworkIntfId: int32(networkInterfaceID),
2802 GemportId: int32(gemPortID), // GemportId not used
2803 Classifier: classifierProto,
2804 Action: actionProto,
2805 Priority: int32(logicalFlow.Priority),
2806 Cookie: logicalFlow.Cookie,
2807 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002808 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002809 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002810 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002811 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002812 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2813 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2814 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002815 }
2816 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002817}
2818
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2820 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302821 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002822 }
2823 if Dir == tp_pb.Direction_UPSTREAM {
2824 return "upstream", nil
2825 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2826 return "downstream", nil
2827 }
2828 return "", nil
2829}
2830
Kent Hagermane6ff1012020-07-14 15:07:53 -04002831// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302832func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002833 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002834 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002835 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002836 intfID := args[IntfID]
2837 onuID := args[OnuID]
2838 uniID := args[UniID]
2839 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002840 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002841 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002842 gemToAes := make(map[uint32]bool)
2843
2844 var attributes []tp.IGemPortAttribute
2845 var direction = tp_pb.Direction_UPSTREAM
2846 switch TpInst := TpInst.(type) {
2847 case *tp.TechProfile:
2848 if IsUpstream(actionInfo[Output].(uint32)) {
2849 attributes = TpInst.UpstreamGemPortAttributeList
2850 } else {
2851 attributes = TpInst.DownstreamGemPortAttributeList
2852 direction = tp_pb.Direction_DOWNSTREAM
2853 }
2854 default:
2855 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2856 return
2857 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002858
2859 if len(gemPorts) == 1 {
2860 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002861 gemPortID = gemPorts[0]
2862 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002863 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2864 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002865 pBitMap := attributes[idx].PbitMap
2866 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2867 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2868 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2869 // this pcp bit traffic.
2870 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2871 if pbitSet == pbit1 {
2872 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2873 pbitToGem[pcp] = gemID
2874 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002875 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002876 }
2877 }
2878 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002879 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2880 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2881 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2882 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002883 }
2884
Gamze Abaka7650be62021-02-26 10:50:36 +00002885 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2886 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2887
salmansiddiqui7ac62132019-08-22 03:58:50 +00002888 if ipProto, ok := classifierInfo[IPProto]; ok {
2889 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002891 "tp-id": tpID,
2892 "alloc-id": allocID,
2893 "intf-id": intfID,
2894 "onu-id": onuID,
2895 "uni-id": uniID,
2896 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002897 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002898 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002899 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002900 }
2901
Girish Gowdra32625212020-04-29 11:26:35 -07002902 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002903 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302904 log.Fields{
2905 "intf-id": intfID,
2906 "onu-id": onuID,
2907 "uni-id": uniID,
2908 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002909 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002910 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002911 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 return
2915 }
2916 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002917 if ethType.(uint32) == EapEthType {
2918 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002919 "intf-id": intfID,
2920 "onu-id": onuID,
2921 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002922 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002923 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 var vlanID uint32
2925 if val, ok := classifierInfo[VlanVid]; ok {
2926 vlanID = (val.(uint32)) & VlanvIDMask
2927 } else {
2928 vlanID = DefaultMgmtVlan
2929 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002930 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002931 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002933 } else if ethType.(uint32) == PPPoEDEthType {
2934 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2935 "tp-id": tpID,
2936 "alloc-id": allocID,
2937 "intf-id": intfID,
2938 "onu-id": onuID,
2939 "uni-id": uniID,
2940 })
2941 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002942 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002943 logger.Warn(ctx, err)
2944 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002946 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002947 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002948 "intf-id": intfID,
2949 "onu-id": onuID,
2950 "uni-id": uniID,
2951 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002952 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002953 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002954 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002956 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002958 "intf-id": intfID,
2959 "onu-id": onuID,
2960 "uni-id": uniID,
2961 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002962 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002963 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002964 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
2966 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302968 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002969 "intf-id": intfID,
2970 "onu-id": onuID,
2971 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302972 "classifier": classifierInfo,
2973 "action": actionInfo,
2974 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 return
2976 }
2977 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002978 go func() {
2979 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2980 logger.Warn(ctx, err)
2981 }
2982 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983}
2984
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002985func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2986 f.flowsUsedByGemPortKey.RLock()
2987 flowIDList := f.flowsUsedByGemPort[gemPortID]
2988 f.flowsUsedByGemPortKey.RUnlock()
2989 return len(flowIDList) > 1
2990
Gamze Abakafee36392019-10-03 11:17:24 +00002991}
2992
npujarec5762e2020-01-01 14:08:48 +05302993func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2994 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002995 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2996 for _, currentGemPort := range currentGemPorts {
2997 for _, tpGemPort := range tpGemPorts {
2998 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2999 return true, currentGemPort
3000 }
3001 }
3002 }
Girish Gowdra54934262019-11-13 14:19:55 +05303003 if tpInst.InstanceCtrl.Onu == "single-instance" {
3004 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003005 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003006 logger.Warn(ctx, err)
3007 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003008 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003009 logger.Warn(ctx, err)
3010 }
Girish Gowdra54934262019-11-13 14:19:55 +05303011
3012 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3013 // still be used on other uni ports.
3014 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3015 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003016 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003017 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303018 for i := 0; i < len(tpInstances); i++ {
3019 tpI := tpInstances[i]
3020 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303021 for _, tpGemPort := range tpGemPorts {
3022 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003023 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303024 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303025 }
3026 }
3027 }
3028 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003030 return false, 0
3031}
3032
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003034 for _, field := range flows.GetOfbFields(flow) {
3035 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003038 } else if field.Type == flows.ETH_DST {
3039 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003041 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003044 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003047 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303048 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003049 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003050 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003053 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003056 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003057 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003062 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003063 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003065 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003066 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003068 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 return
3074 }
3075 }
3076}
3077
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003079 for _, action := range flows.GetActions(flow) {
3080 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003082 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003085 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003086 }
Scott Baker355d1742019-10-24 10:57:52 -07003087 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003090 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 if out := action.GetPush(); out != nil {
3092 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003094 } else {
3095 actionInfo[PushVlan] = true
3096 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303098 log.Fields{
3099 "push-tpid": actionInfo[TPID].(uint32),
3100 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 }
3102 }
Scott Baker355d1742019-10-24 10:57:52 -07003103 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 if out := action.GetSetField(); out != nil {
3105 if field := out.GetField(); field != nil {
3106 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003107 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3110 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 }
3112 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003113 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003116 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 }
3118 }
3119 return nil
3120}
3121
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003123 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003124 fieldtype := ofbField.GetType()
3125 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003126 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3127 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003129 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003130 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003131 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003132 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3133 pcp := ofbField.GetVlanPcp()
3134 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003135 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003138 }
3139 }
3140}
3141
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003143 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003145 } else {
3146 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003148 }
3149}
3150
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003152 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003153 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3155 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003156 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003157 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003158 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303159 log.Fields{
3160 "newinport": classifierInfo[InPort].(uint32),
3161 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003162 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303163 return olterrors.NewErrNotFound("child-in-port",
3164 log.Fields{
3165 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3166 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003167 }
3168 }
3169 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003170 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003171 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003172 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003173 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003174 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303176 log.Fields{
3177 "newoutport": actionInfo[Output].(uint32),
3178 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003179 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303180 return olterrors.NewErrNotFound("out-port",
3181 log.Fields{
3182 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3183 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003184 }
3185 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3186 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003187 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003188 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003189 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303190 log.Fields{
3191 "newinport": actionInfo[Output].(uint32),
3192 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003193 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303194 return olterrors.NewErrNotFound("nni-port",
3195 log.Fields{
3196 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3197 "in-port": classifierInfo[InPort].(uint32),
3198 "out-port": actionInfo[Output].(uint32),
3199 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 }
3201 }
3202 }
3203 return nil
3204}
Gamze Abakafee36392019-10-03 11:17:24 +00003205
Neha Sharma96b7bf22020-06-15 10:37:32 +00003206func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003207 /* Metadata 8 bytes:
3208 Most Significant 2 Bytes = Inner VLAN
3209 Next 2 Bytes = Tech Profile ID(TPID)
3210 Least Significant 4 Bytes = Port ID
3211 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3212 subscriber related flows.
3213 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003215 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003216 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003217 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003219 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003220}
3221
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003222func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3223 for _, sliceElement := range slice {
3224 if sliceElement == item {
3225 return slice
3226 }
3227 }
3228 return append(slice, item)
3229}
3230
3231func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003232 for _, sliceElement := range slice {
3233 if sliceElement == item {
3234 return slice
3235 }
3236 }
3237 return append(slice, item)
3238}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303239
3240// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003241func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303242
3243 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3244 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003245 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003246 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248 log.Fields{
3249 "port-number": action[Output].(uint32),
3250 "error": err})
3251 return uint32(0), err
3252 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303254 return intfID, nil
3255 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003257 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003258 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003259 log.Fields{
3260 "port-number": action[Output].(uint32),
3261 "error": err})
3262 return uint32(0), err
3263 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003264 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303265 return intfID, nil
3266 }
3267 return uint32(0), nil
3268}
3269
3270// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003271func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3272 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3273 if err != nil {
3274 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3275 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3276 return
3277 }
3278 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003279
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003280 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003281 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003282 f.packetInGemPortLock.RUnlock()
3283
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303284 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003285 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003286 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 +05303287 log.Fields{
3288 "pktinkey": pktInkey,
3289 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003290 return
3291 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303292 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003293 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003294 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003295 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003296
npujarec5762e2020-01-01 14:08:48 +05303297 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003298 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 +05303299 log.Fields{
3300 "pktinkey": pktInkey,
3301 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303302}
3303
Esin Karaman7fb80c22020-07-16 14:23:33 +00003304//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3305func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3306 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003307 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003308 return 0, 0, errors.New("invalid packet length")
3309 }
3310 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3311 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3312
3313 var index int8
3314 if outerEthType == 0x8100 {
3315 if innerEthType == 0x8100 {
3316 // q-in-q 802.1ad or 802.1q double tagged packet.
3317 // get the inner vlanId
3318 index = 18
3319 } else {
3320 index = 14
3321 }
3322 priority := (packet[index] >> 5) & 0x7
3323 //13 bits composes vlanId value
3324 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3325 return vlan, priority, nil
3326 }
3327 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3328 return 0, 0, nil
3329}
3330
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303331// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303332func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003333
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003334 f.onuGemInfoLock.Lock()
3335 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003336
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003337 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303338 for idx, onu := range onugem {
3339 if onu.OnuID == onuID {
3340 for _, uni := range onu.UniPorts {
3341 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003342 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 +05303343 return
3344 }
3345 }
3346 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003347 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303348 }
3349 }
npujarec5762e2020-01-01 14:08:48 +05303350 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003351
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303352}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303353
npujarec5762e2020-01-01 14:08:48 +05303354func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3355 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303356 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003357 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303358 return
3359 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003360 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303361 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003362 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303363 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003364 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303365}
Esin Karamanccb714b2019-11-29 15:02:06 +00003366
Girish Gowdra9602eb42020-09-09 15:50:39 -07003367//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3368// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003369func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003370 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003371 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003372 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3373 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3374
Esin Karamanccb714b2019-11-29 15:02:06 +00003375 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003376 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 -07003377 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003378 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003379
3380 var onuID = int32(NoneOnuID)
3381 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003382 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3383 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3384 log.Fields{
3385 "flow": flow,
3386 "device-id": f.deviceHandler.device.Id,
3387 "intf-id": networkInterfaceID,
3388 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003389 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003390 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3391 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3392 log.Fields{
3393 "flow": flowInfo.Flow,
3394 "flow-id": flow.Id,
3395 "device-id": f.deviceHandler.device.Id})
3396 // Remove from device
3397 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3398 // DKB
3399 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3400 log.Fields{
3401 "flow-id": flow.Id,
3402 "error": err})
3403 return err
3404 }
3405 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003406 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003407}
3408
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003409// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3410func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3411 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3412 if err != nil {
3413 _ = olterrors.NewErrNotFound("onu", log.Fields{
3414 "pon-port": f.ponPortIdx}, err).Log()
3415 return
3416 }
3417
3418 f.subscriberDataPathFlowIDMapLock.Lock()
3419 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3420
3421 for _, onu := range onuGemInfo {
3422 for _, uniID := range onu.UniPorts {
3423 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3424 if err != nil {
3425 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3426 }
3427 for _, flowID := range flowIDs {
3428 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3429 if flowInfo == nil {
3430 // Error is already logged in the called function
3431 continue
3432 }
3433 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3434 flowInfo.Flow.FlowType == Downstream &&
3435 flowInfo.Flow.Classifier.OVid > 0 &&
3436 flowInfo.Flow.TechProfileId > 0 {
3437 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3438 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3439 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3440 }
3441 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3442 flowInfo.Flow.FlowType == Upstream &&
3443 flowInfo.Flow.Action.OVid > 0 &&
3444 flowInfo.Flow.TechProfileId > 0 {
3445 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3446 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3447 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3448 }
3449 }
3450 }
3451 }
3452 }
3453}
3454
3455// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3456func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3457 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3458}