blob: 4e10522608c1dfdfcd1e7d1919bbdc78ab947939 [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,
1879 gemPortID int32, flowID uint64, portNum uint32, direction string) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001880
Neha Sharma96b7bf22020-06-15 10:37:32 +00001881 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001882 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301883 return olterrors.NewErrNotFound("tp-id",
1884 log.Fields{
1885 "flow": flow,
Girish Gowdraa482f272021-03-24 23:04:19 -07001886 "intf-id": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301887 "onu-id": onuID,
1888 "uni-id": uniID,
1889 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001890 }
Gamze Abakafee36392019-10-03 11:17:24 +00001891
Girish Gowdraa482f272021-03-24 23:04:19 -07001892 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1893 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001894 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1895 log.Fields{
1896 "tpPath": tpPath,
1897 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001898 techprofileInst, err := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001899 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1900 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1901 log.Fields{
1902 "tp-id": tpID,
1903 "path": tpPath}, err)
1904 }
1905
1906 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1907
1908 if used {
1909 f.flowsUsedByGemPortKey.Lock()
1910 defer f.flowsUsedByGemPortKey.Unlock()
1911
1912 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1913 for i, flowIDinMap := range flowIDs {
1914 if flowIDinMap == flowID {
1915 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1916 // everytime flowsUsedByGemPort cache is updated the same should be updated
1917 // in kv store by calling UpdateFlowIDsForGem
1918 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
Girish Gowdraa482f272021-03-24 23:04:19 -07001919 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001920 return err
1921 }
1922 break
1923 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001924 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1926 log.Fields{
1927 "gemport-id": gemPortID,
1928 "usedByFlows": flowIDs,
1929 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001930
1931 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, intfID, uint32(onuID), uint32(uniID), tpID, false); err != nil {
1932 return err
1933 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934 return nil
1935 }
1936 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 -07001937 f.resourceMgr.RemoveGemPortIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001938 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1939 // 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 -07001940 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), intfID)
Esin Karamandf392e12020-12-16 13:33:09 +00001941 // also clear gem to uni cache
1942 f.removeFromGemToUniMap(gemPortKey{
Girish Gowdraa482f272021-03-24 23:04:19 -07001943 intfID: intfID,
Esin Karamandf392e12020-12-16 13:33:09 +00001944 gemPort: uint32(gemPortID),
1945 })
Girish Gowdraa482f272021-03-24 23:04:19 -07001946 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001947
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001948 f.onuIdsLock.Lock() // TODO: What is this lock?
1949
1950 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1951 // by calling DeleteFlowIDsForGem
1952 f.flowsUsedByGemPortKey.Lock()
1953 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1954 f.flowsUsedByGemPortKey.Unlock()
Girish Gowdraa482f272021-03-24 23:04:19 -07001955 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1956 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001957
1958 f.onuIdsLock.Unlock()
1959
1960 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001961 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1963 log.Fields{
1964 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001965 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001966 "onu-id": onuID,
1967 "uni-id": uniID,
1968 "device-id": f.deviceHandler.device.Id,
1969 "gemport-id": gemPortID})
1970 }
1971 switch techprofileInst := techprofileInst.(type) {
1972 case *tp.TechProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001973 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001975 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 logger.Warn(ctx, err)
1977 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001978 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 logger.Warn(ctx, err)
1980 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001981 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 -07001982 logger.Warn(ctx, err)
1983 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001984 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 -07001985 logger.Warn(ctx, err)
1986 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001987 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001988 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001989 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001990 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1991 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001992 "intf": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001993 "onu-id": onuID,
1994 "uni-id": uniID,
1995 "device-id": f.deviceHandler.device.Id,
1996 "alloc-id": techprofileInst.UsScheduler.AllocID})
1997 }
1998 }
1999 case *tp.EponProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07002000 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 logger.Warn(ctx, err)
2002 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002003 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002004 logger.Warn(ctx, err)
2005 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002006 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002007 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07002008 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002009 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302010 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002011 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302012 "onu-id": onuID,
2013 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002014 "device-id": f.deviceHandler.device.Id,
2015 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00002016 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002017 default:
2018 logger.Errorw(ctx, "error-unknown-tech",
2019 log.Fields{
2020 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002021 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002022
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302023 return nil
2024}
2025
David K. Bainbridge794735f2020-02-11 21:01:37 -08002026// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002027func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002028 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302030 log.Fields{
2031 "flowDirection": flowDirection,
2032 "flow": *flow,
2033 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002034
2035 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002037 }
2038
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039 classifierInfo := make(map[string]interface{})
2040
Neha Sharma96b7bf22020-06-15 10:37:32 +00002041 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302042 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302045 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302046
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 onuID := int32(onu)
2048 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302049
2050 for _, field := range flows.GetOfbFields(flow) {
2051 if field.Type == flows.IP_PROTO {
2052 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302054 }
2055 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302057 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002058 "flow-id": flow.Id,
2059 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302060 "onu-id": onuID,
2061 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302062
2063 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2064 onuID = -1
2065 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2067 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002068 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002070 log.Fields{
2071 "port-number": inPort,
2072 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002073 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002074 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302075 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2077 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})
2078 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2079 }
2080 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2081 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2082 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2083 return err
2084 }
2085 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2086 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2087 return err
2088 }
2089 if !flowInfo.Flow.ReplicateFlow {
Girish Gowdraa482f272021-03-24 23:04:19 -07002090 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum, flowDirection); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002091 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002092 "flow-id": flow.Id,
2093 "stored-flow": flowInfo.Flow,
2094 "device-id": f.deviceHandler.device.Id,
2095 "stored-flow-id": flowInfo.Flow.FlowId,
2096 "onu-id": onuID,
2097 "intf": Intf,
2098 })
2099 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302100 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002101 } else {
2102 gems := make([]uint32, 0)
2103 for _, gem := range flowInfo.Flow.PbitToGemport {
2104 gems = appendUnique32bit(gems, gem)
2105 }
2106 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2107 for _, gem := range gems {
Girish Gowdraa482f272021-03-24 23:04:19 -07002108 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum, flowDirection); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002109 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002110 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002111 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002112 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002113 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002114 "onu-id": onuID,
2115 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002116 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002117 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002118 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302119 }
2120 }
2121 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002122
2123 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2124 if isDatapathFlow(flow) {
2125 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2126 var inverseDirection string
2127 if flowDirection == Upstream {
2128 inverseDirection = Downstream
2129 } else {
2130 inverseDirection = Upstream
2131 }
2132
2133 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002134 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002135 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002136 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002137 }
2138 }
2139 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002140}
2141
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002142//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002143func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002144
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302146 var direction string
2147 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002148
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302149 for _, action := range flows.GetActions(flow) {
2150 if action.Type == flows.OUTPUT {
2151 if out := action.GetOutput(); out != nil {
2152 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002153 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302154 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002156 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002157 }
2158 }
2159 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002160
2161 if flows.HasGroup(flow) {
2162 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002163 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002164 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302165 direction = Upstream
2166 } else {
2167 direction = Downstream
2168 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302169
Girish Gowdracefae192020-03-19 18:14:10 -07002170 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002171 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002172
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002173 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002174}
2175
Esin Karamanae41e2b2019-12-17 18:13:13 +00002176//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2177func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2178 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2179 if ethType, ok := classifierInfo[EthType]; ok {
2180 if ethType.(uint32) == IPv4EthType {
2181 if ipProto, ok := classifierInfo[IPProto]; ok {
2182 if ipProto.(uint32) == IgmpProto {
2183 return true
2184 }
2185 }
2186 }
2187 }
2188 }
2189 return false
2190}
2191
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002192// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2193func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2194 // Step1 : Fill flowControlBlock
2195 // Step2 : Push the flowControlBlock to ONU channel
2196 // Step3 : Wait on response channel for response
2197 // Step4 : Return error value
2198 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2199 errChan := make(chan error)
2200 flowCb := flowControlBlock{
2201 ctx: ctx,
2202 addFlow: addFlow,
2203 flow: flow,
2204 flowMetadata: flowMetadata,
2205 errChan: &errChan,
2206 }
2207 inPort, outPort := getPorts(flow)
2208 var onuID uint32
2209 if inPort != InvalidPort && outPort != InvalidPort {
2210 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2211 }
2212 // inPort or outPort is InvalidPort for trap-from-nni flows.
2213 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2214 // Send the flowCb on the ONU flow channel
2215 f.incomingFlows[onuID] <- flowCb
2216 // Wait on the channel for flow handlers return value
2217 err := <-errChan
2218 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2219 return err
2220}
2221
2222// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2223// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2224func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2225 for {
2226 // block on the channel to receive an incoming flow
2227 // process the flow completely before proceeding to handle the next flow
2228 flowCb := <-subscriberFlowChannel
2229 if flowCb.addFlow {
2230 logger.Debugw(flowCb.ctx, "adding-flow",
2231 log.Fields{"device-id": f.deviceHandler.device.Id,
2232 "flowToAdd": flowCb.flow})
2233 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2234 // Pass the return value over the return channel
2235 *flowCb.errChan <- err
2236 } else {
2237 logger.Debugw(flowCb.ctx, "removing-flow",
2238 log.Fields{"device-id": f.deviceHandler.device.Id,
2239 "flowToRemove": flowCb.flow})
2240 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2241 // Pass the return value over the return channel
2242 *flowCb.errChan <- err
2243 }
2244 }
2245}
2246
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002247// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302248// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002249func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002250 classifierInfo := make(map[string]interface{})
2251 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002252 var UsMeterID uint32
2253 var DsMeterID uint32
2254
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302256 log.Fields{
2257 "flow": flow,
2258 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002260
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002262 if err != nil {
2263 // Error logging is already done in the called function
2264 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002265 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302266 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002267
Esin Karamanccb714b2019-11-29 15:02:06 +00002268 if flows.HasGroup(flow) {
2269 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002270 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002271 }
2272
manikkaraj k17652a72019-05-06 09:06:36 -04002273 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002275 if err != nil {
2276 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002277 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002278 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002279
Neha Sharma96b7bf22020-06-15 10:37:32 +00002280 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302281 log.Fields{
2282 "classifierinfo_inport": classifierInfo[InPort],
2283 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002284 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002285
Humera Kouser94d7a842019-08-25 19:04:32 -04002286 if ethType, ok := classifierInfo[EthType]; ok {
2287 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002288 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002289 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002290 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002291 if ethType.(uint32) == PPPoEDEthType {
2292 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2293 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2294 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2295 }
2296 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002297 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002298 if ipProto, ok := classifierInfo[IPProto]; ok {
2299 if ipProto.(uint32) == IPProtoDhcp {
2300 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302301 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002302 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002303 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002304 }
2305 }
2306 }
2307 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002308 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002310 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002311 }
A R Karthick1f85b802019-10-11 05:06:05 +00002312
npujarec5762e2020-01-01 14:08:48 +05302313 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002314
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002316 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302317 return olterrors.NewErrNotFound("tpid-for-flow",
2318 log.Fields{
2319 "flow": flow,
2320 "intf-id": IntfID,
2321 "onu-id": onuID,
2322 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002323 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002324 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302325 log.Fields{
2326 "tp-id": TpID,
2327 "intf-id": intfID,
2328 "onu-id": onuID,
2329 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002330 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002331 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002332 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002333 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002334 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002336
2337 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002338 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002339}
Girish Gowdra3d633032019-12-10 16:37:05 +05302340
Esin Karamanccb714b2019-11-29 15:02:06 +00002341// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002342func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002343 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302345 "classifier-info": classifierInfo,
2346 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002347
Esin Karaman65409d82020-03-18 10:58:18 +00002348 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002349 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002350 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002351 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002352
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002353 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002354
David K. Bainbridge794735f2020-02-11 21:01:37 -08002355 onuID := NoneOnuID
2356 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002357
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002358 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002360 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002362 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2363 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002364 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002365 }
2366 groupID := actionInfo[GroupID].(uint32)
2367 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002368 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002369 FlowType: Multicast,
2370 NetworkIntfId: int32(networkInterfaceID),
2371 GroupId: groupID,
2372 Classifier: classifierProto,
2373 Priority: int32(flow.Priority),
2374 Cookie: flow.Cookie}
2375
Kent Hagermane6ff1012020-07-14 15:07:53 -04002376 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002377 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002378 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002379 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002380 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002381 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002382 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002383 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002384 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002385 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002386 //cached group can be removed now
2387 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2388 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2389 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002390 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002391
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002392 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2393 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2394 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002395 }
2396 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002397}
2398
Esin Karaman65409d82020-03-18 10:58:18 +00002399//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2400func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2401 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002403 if err != nil {
2404 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2405 }
2406 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002407 }
Esin Karaman65409d82020-03-18 10:58:18 +00002408 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302409 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002410 if e == nil && len(nniPorts) > 0 {
2411 return nniPorts[0], nil
2412 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302413 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002414}
2415
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002416//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002418
Neha Sharma96b7bf22020-06-15 10:37:32 +00002419 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302420 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002421 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302422 log.Fields{
2423 "intf-id": intfID,
2424 "onu-id": onuID,
2425 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002426 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302427 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002428 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002429
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002431 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002433 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002434 tpDownloadMsg,
2435 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002436 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002437 onuDev.deviceType,
2438 onuDev.deviceID,
2439 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002440 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302441 return olterrors.NewErrCommunication("send-techprofile-download-request",
2442 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002443 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302444 "to-adapter": onuDev.deviceType,
2445 "onu-id": onuDev.deviceID,
2446 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002447 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302449 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302450}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002451
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302452//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002453func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302454
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002455 f.onuGemInfoLock.Lock()
2456 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002457 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002458 // If the ONU already exists in onuGemInfo list, nothing to do
2459 for _, onu := range onugem {
2460 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2461 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2462 log.Fields{"onuID": onuID,
2463 "serialNum": serialNum})
2464 return nil
2465 }
2466 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002467
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302468 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002469 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002470 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002471 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302472 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302474 log.Fields{
2475 "intf-id": intfID,
2476 "onu-id": onuID,
2477 "serial-num": serialNum,
2478 "onu": onu,
2479 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002480 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002481}
2482
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302483//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302484func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002485
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002486 f.onuGemInfoLock.Lock()
2487 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002488
Neha Sharma96b7bf22020-06-15 10:37:32 +00002489 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302490 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002491 "gem-port-id": gemPort,
2492 "intf-id": intfID,
2493 "onu-id": onuID,
2494 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002495 "onu-gem": f.onuGemInfo})
2496 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302497 // update the gem to the local cache as well as to kv strore
2498 for idx, onu := range onugem {
2499 if onu.OnuID == onuID {
2500 // check if gem already exists , else update the cache and kvstore
2501 for _, gem := range onu.GemPorts {
2502 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002503 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302504 log.Fields{
2505 "gem": gemPort,
2506 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 return
2508 }
2509 }
2510 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002511 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002512 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302513 }
2514 }
npujarec5762e2020-01-01 14:08:48 +05302515 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302516 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002517 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302518 log.Fields{
2519 "intf-id": intfID,
2520 "onu-id": onuID,
2521 "gemPort": gemPort,
2522 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002523 return
2524 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302526 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002527 "gem-port-id": gemPort,
2528 "intf-id": intfID,
2529 "onu-id": onuID,
2530 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002531 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002532}
2533
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002534//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302535func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002536 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002537 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538 var err error
2539
2540 if packetIn.IntfType == "pon" {
2541 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002542 // get onu and uni ids associated with the given pon and gem ports
2543 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002544 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 return logicalPortNum, err
2546 }
Esin Karamandf392e12020-12-16 13:33:09 +00002547 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2548
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549 if packetIn.PortNo != 0 {
2550 logicalPortNum = packetIn.PortNo
2551 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002552 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002553 }
2554 // 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 +00002555 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002556 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002557 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002559
2560 if logger.V(log.DebugLevel) {
2561 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2562 log.Fields{
2563 "logical-port-num": logicalPortNum,
2564 "intf-type": packetIn.IntfType,
2565 "packet": hex.EncodeToString(packetIn.Pkt),
2566 })
2567 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002568 return logicalPortNum, nil
2569}
2570
Esin Karamandf392e12020-12-16 13:33:09 +00002571//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2572func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2573 key := gemPortKey{
2574 intfID: intfID,
2575 gemPort: gemPortID,
2576 }
2577 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2578 if ok {
2579 if len(uniPortInfo) > 1 {
2580 //return onu ID and uni port from the cache
2581 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2582 log.Fields{
2583 "intfID": intfID,
2584 "gemPortID": gemPortID,
2585 "onuID, uniID": uniPortInfo})
2586 return uniPortInfo[0], uniPortInfo[1], nil
2587 }
2588 }
2589 //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.
2590 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2591 if err == nil {
2592 f.toGemToUniMap(ctx, key, onuID, uniID)
2593 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2594 log.Fields{
2595 "gemPortKey": key,
2596 "onuID": onuID,
2597 "uniID": uniID})
2598 return onuID, uniID, nil
2599 }
2600 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2601 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2602 errors.New("no uni port found"))
2603}
2604
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002605//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002606func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002607 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002608
2609 ctag, priority, err := getCTagFromPacket(ctx, packet)
2610 if err != nil {
2611 return 0, err
2612 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302613
Esin Karaman7fb80c22020-07-16 14:23:33 +00002614 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002615 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002616 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002617 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002618 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302619 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002620 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302621 log.Fields{
2622 "pktinkey": pktInkey,
2623 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002624
2625 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002626 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302627 //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 +00002628 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302629 if err == nil {
2630 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002631 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002633 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002634 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302635 log.Fields{
2636 "pktinkey": pktInkey,
2637 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302638 return gemPortID, nil
2639 }
2640 }
Shrey Baid26912972020-04-16 21:02:31 +05302641 return uint32(0), olterrors.NewErrNotFound("gem-port",
2642 log.Fields{
2643 "pktinkey": pktInkey,
2644 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002645
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646}
2647
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002648func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2649 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002650 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002651 classifier[PacketTagType] = DoubleTag
2652 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 /* We manage flowId resource pool on per PON port basis.
2654 Since this situation is tricky, as a hack, we pass the NNI port
2655 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002656 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657 on NNI port, use onu_id as -1 (invalid)
2658 ****************** CAVEAT *******************
2659 This logic works if the NNI Port Id falls within the same valid
2660 range of PON Port Ids. If this doesn't work for some OLT Vendor
2661 we need to have a re-look at this.
2662 *********************************************
2663 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002664 onuID := -1
2665 uniID := -1
2666 gemPortID := -1
2667 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002668 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302669 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302670 return olterrors.NewErrNotFound("nni-intreface-id",
2671 log.Fields{
2672 "classifier": classifier,
2673 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002674 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302675 }
2676
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002677 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002678 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002680 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002681
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002682 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2683 log.Fields{
2684 "classifier": classifier,
2685 "action": action,
2686 "flowId": logicalFlow.Id,
2687 "intf-id": networkInterfaceID})
2688
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 classifierProto, err := makeOpenOltClassifierField(classifier)
2690 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002691 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002692 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002693 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002694 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002695 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002696 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002697 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002698 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002699 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2700 OnuId: int32(onuID), // OnuId not required
2701 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002702 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002703 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002704 AllocId: int32(allocID), // AllocId not used
2705 NetworkIntfId: int32(networkInterfaceID),
2706 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002707 Classifier: classifierProto,
2708 Action: actionProto,
2709 Priority: int32(logicalFlow.Priority),
2710 Cookie: logicalFlow.Cookie,
2711 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002712 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002713 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002714 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002715 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002716 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2717 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2718 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002719 }
2720 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002721}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002722
Esin Karamanae41e2b2019-12-17 18:13:13 +00002723//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2724func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2725 var packetType string
2726 ovid, ivid := false, false
2727 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2728 vid := vlanID & VlanvIDMask
2729 if vid != ReservedVlan {
2730 ovid = true
2731 }
2732 }
2733 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2734 vid := uint32(metadata)
2735 if vid != ReservedVlan {
2736 ivid = true
2737 }
2738 }
2739 if ovid && ivid {
2740 packetType = DoubleTag
2741 } else if !ovid && !ivid {
2742 packetType = Untagged
2743 } else {
2744 packetType = SingleTag
2745 }
2746 return packetType
2747}
2748
2749//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002750func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002752 action := make(map[string]interface{})
2753 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2754 action[TrapToHost] = true
2755 /* We manage flowId resource pool on per PON port basis.
2756 Since this situation is tricky, as a hack, we pass the NNI port
2757 index (network_intf_id) as PON port Index for the flowId resource
2758 pool. Also, there is no ONU Id available for trapping packets
2759 on NNI port, use onu_id as -1 (invalid)
2760 ****************** CAVEAT *******************
2761 This logic works if the NNI Port Id falls within the same valid
2762 range of PON Port Ids. If this doesn't work for some OLT Vendor
2763 we need to have a re-look at this.
2764 *********************************************
2765 */
2766 onuID := -1
2767 uniID := -1
2768 gemPortID := -1
2769 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002771 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302772 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002773 "classifier": classifier,
2774 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002775 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002776 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002777 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002778 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002779 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002780 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002781
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 classifierProto, err := makeOpenOltClassifierField(classifier)
2783 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002784 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002785 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002786 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002787 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002788 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002789 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002790 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002791 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2793 OnuId: int32(onuID), // OnuId not required
2794 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002795 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002796 FlowType: Downstream,
2797 AllocId: int32(allocID), // AllocId not used
2798 NetworkIntfId: int32(networkInterfaceID),
2799 GemportId: int32(gemPortID), // GemportId not used
2800 Classifier: classifierProto,
2801 Action: actionProto,
2802 Priority: int32(logicalFlow.Priority),
2803 Cookie: logicalFlow.Cookie,
2804 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002805 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002806 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002807 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002808 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002809 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2810 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2811 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002812 }
2813 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002814}
2815
salmansiddiqui7ac62132019-08-22 03:58:50 +00002816func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2817 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302818 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819 }
2820 if Dir == tp_pb.Direction_UPSTREAM {
2821 return "upstream", nil
2822 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2823 return "downstream", nil
2824 }
2825 return "", nil
2826}
2827
Kent Hagermane6ff1012020-07-14 15:07:53 -04002828// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302829func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002830 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002831 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002832 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002833 intfID := args[IntfID]
2834 onuID := args[OnuID]
2835 uniID := args[UniID]
2836 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002837 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002839 gemToAes := make(map[uint32]bool)
2840
2841 var attributes []tp.IGemPortAttribute
2842 var direction = tp_pb.Direction_UPSTREAM
2843 switch TpInst := TpInst.(type) {
2844 case *tp.TechProfile:
2845 if IsUpstream(actionInfo[Output].(uint32)) {
2846 attributes = TpInst.UpstreamGemPortAttributeList
2847 } else {
2848 attributes = TpInst.DownstreamGemPortAttributeList
2849 direction = tp_pb.Direction_DOWNSTREAM
2850 }
2851 default:
2852 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2853 return
2854 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002855
2856 if len(gemPorts) == 1 {
2857 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002858 gemPortID = gemPorts[0]
2859 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002860 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2861 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002862 pBitMap := attributes[idx].PbitMap
2863 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2864 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2865 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2866 // this pcp bit traffic.
2867 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2868 if pbitSet == pbit1 {
2869 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2870 pbitToGem[pcp] = gemID
2871 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002872 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 }
2874 }
2875 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002876 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2877 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2878 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2879 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002880 }
2881
Gamze Abaka7650be62021-02-26 10:50:36 +00002882 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2883 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2884
salmansiddiqui7ac62132019-08-22 03:58:50 +00002885 if ipProto, ok := classifierInfo[IPProto]; ok {
2886 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002888 "tp-id": tpID,
2889 "alloc-id": allocID,
2890 "intf-id": intfID,
2891 "onu-id": onuID,
2892 "uni-id": uniID,
2893 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002894 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002896 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002897 }
2898
Girish Gowdra32625212020-04-29 11:26:35 -07002899 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302901 log.Fields{
2902 "intf-id": intfID,
2903 "onu-id": onuID,
2904 "uni-id": uniID,
2905 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002906 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002907 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002908 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002910 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002911 return
2912 }
2913 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002914 if ethType.(uint32) == EapEthType {
2915 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002916 "intf-id": intfID,
2917 "onu-id": onuID,
2918 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002919 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002920 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002921 var vlanID uint32
2922 if val, ok := classifierInfo[VlanVid]; ok {
2923 vlanID = (val.(uint32)) & VlanvIDMask
2924 } else {
2925 vlanID = DefaultMgmtVlan
2926 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002927 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002928 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002929 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002930 } else if ethType.(uint32) == PPPoEDEthType {
2931 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2932 "tp-id": tpID,
2933 "alloc-id": allocID,
2934 "intf-id": intfID,
2935 "onu-id": onuID,
2936 "uni-id": uniID,
2937 })
2938 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002939 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002940 logger.Warn(ctx, err)
2941 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002943 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002944 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002945 "intf-id": intfID,
2946 "onu-id": onuID,
2947 "uni-id": uniID,
2948 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002949 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002950 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002951 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002952 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002953 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002954 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002955 "intf-id": intfID,
2956 "onu-id": onuID,
2957 "uni-id": uniID,
2958 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002959 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002960 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002961 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002962 }
2963 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002964 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302965 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002966 "intf-id": intfID,
2967 "onu-id": onuID,
2968 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302969 "classifier": classifierInfo,
2970 "action": actionInfo,
2971 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 return
2973 }
2974 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002975 go func() {
2976 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2977 logger.Warn(ctx, err)
2978 }
2979 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980}
2981
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002982func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2983 f.flowsUsedByGemPortKey.RLock()
2984 flowIDList := f.flowsUsedByGemPort[gemPortID]
2985 f.flowsUsedByGemPortKey.RUnlock()
2986 return len(flowIDList) > 1
2987
Gamze Abakafee36392019-10-03 11:17:24 +00002988}
2989
npujarec5762e2020-01-01 14:08:48 +05302990func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2991 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002992 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2993 for _, currentGemPort := range currentGemPorts {
2994 for _, tpGemPort := range tpGemPorts {
2995 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2996 return true, currentGemPort
2997 }
2998 }
2999 }
Girish Gowdra54934262019-11-13 14:19:55 +05303000 if tpInst.InstanceCtrl.Onu == "single-instance" {
3001 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003002 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003003 logger.Warn(ctx, err)
3004 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003005 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003006 logger.Warn(ctx, err)
3007 }
Girish Gowdra54934262019-11-13 14:19:55 +05303008
3009 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3010 // still be used on other uni ports.
3011 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3012 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003013 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303015 for i := 0; i < len(tpInstances); i++ {
3016 tpI := tpInstances[i]
3017 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303018 for _, tpGemPort := range tpGemPorts {
3019 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003020 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303021 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303022 }
3023 }
3024 }
3025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003027 return false, 0
3028}
3029
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003031 for _, field := range flows.GetOfbFields(flow) {
3032 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003035 } else if field.Type == flows.ETH_DST {
3036 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003038 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003041 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003044 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303045 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003047 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003049 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003050 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003053 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003056 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003057 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003062 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003063 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003065 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003068 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 return
3071 }
3072 }
3073}
3074
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003076 for _, action := range flows.GetActions(flow) {
3077 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003079 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003082 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 }
Scott Baker355d1742019-10-24 10:57:52 -07003084 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003087 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 if out := action.GetPush(); out != nil {
3089 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 } else {
3092 actionInfo[PushVlan] = true
3093 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303095 log.Fields{
3096 "push-tpid": actionInfo[TPID].(uint32),
3097 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 }
3099 }
Scott Baker355d1742019-10-24 10:57:52 -07003100 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 if out := action.GetSetField(); out != nil {
3102 if field := out.GetField(); field != nil {
3103 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003104 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3107 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
3109 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003110 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003113 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 }
3115 }
3116 return nil
3117}
3118
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003121 fieldtype := ofbField.GetType()
3122 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003123 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3124 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003126 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003127 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003128 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003129 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3130 pcp := ofbField.GetVlanPcp()
3131 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003132 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003134 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003135 }
3136 }
3137}
3138
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003140 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003141 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003142 } else {
3143 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003145 }
3146}
3147
Neha Sharma96b7bf22020-06-15 10:37:32 +00003148func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003149 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3152 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003153 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303156 log.Fields{
3157 "newinport": classifierInfo[InPort].(uint32),
3158 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303160 return olterrors.NewErrNotFound("child-in-port",
3161 log.Fields{
3162 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3163 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003164 }
3165 }
3166 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003167 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003168 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003169 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003170 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003171 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003172 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303173 log.Fields{
3174 "newoutport": actionInfo[Output].(uint32),
3175 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003176 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303177 return olterrors.NewErrNotFound("out-port",
3178 log.Fields{
3179 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3180 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003181 }
3182 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3183 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003184 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003185 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303187 log.Fields{
3188 "newinport": actionInfo[Output].(uint32),
3189 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003190 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303191 return olterrors.NewErrNotFound("nni-port",
3192 log.Fields{
3193 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3194 "in-port": classifierInfo[InPort].(uint32),
3195 "out-port": actionInfo[Output].(uint32),
3196 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003197 }
3198 }
3199 }
3200 return nil
3201}
Gamze Abakafee36392019-10-03 11:17:24 +00003202
Neha Sharma96b7bf22020-06-15 10:37:32 +00003203func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003204 /* Metadata 8 bytes:
3205 Most Significant 2 Bytes = Inner VLAN
3206 Next 2 Bytes = Tech Profile ID(TPID)
3207 Least Significant 4 Bytes = Port ID
3208 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3209 subscriber related flows.
3210 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003212 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003213 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003214 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003215 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003216 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003217}
3218
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003219func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3220 for _, sliceElement := range slice {
3221 if sliceElement == item {
3222 return slice
3223 }
3224 }
3225 return append(slice, item)
3226}
3227
3228func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003229 for _, sliceElement := range slice {
3230 if sliceElement == item {
3231 return slice
3232 }
3233 }
3234 return append(slice, item)
3235}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303236
3237// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003238func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303239
3240 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3241 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003242 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003243 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003244 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003245 log.Fields{
3246 "port-number": action[Output].(uint32),
3247 "error": err})
3248 return uint32(0), err
3249 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003250 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303251 return intfID, nil
3252 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003254 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003256 log.Fields{
3257 "port-number": action[Output].(uint32),
3258 "error": err})
3259 return uint32(0), err
3260 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303262 return intfID, nil
3263 }
3264 return uint32(0), nil
3265}
3266
3267// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003268func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3269 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3270 if err != nil {
3271 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3272 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3273 return
3274 }
3275 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003276
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003277 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003278 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003279 f.packetInGemPortLock.RUnlock()
3280
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303281 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003282 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003283 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 +05303284 log.Fields{
3285 "pktinkey": pktInkey,
3286 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003287 return
3288 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303289 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003290 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003291 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003292 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003293
npujarec5762e2020-01-01 14:08:48 +05303294 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003295 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 +05303296 log.Fields{
3297 "pktinkey": pktInkey,
3298 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303299}
3300
Esin Karaman7fb80c22020-07-16 14:23:33 +00003301//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3302func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3303 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003304 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003305 return 0, 0, errors.New("invalid packet length")
3306 }
3307 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3308 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3309
3310 var index int8
3311 if outerEthType == 0x8100 {
3312 if innerEthType == 0x8100 {
3313 // q-in-q 802.1ad or 802.1q double tagged packet.
3314 // get the inner vlanId
3315 index = 18
3316 } else {
3317 index = 14
3318 }
3319 priority := (packet[index] >> 5) & 0x7
3320 //13 bits composes vlanId value
3321 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3322 return vlan, priority, nil
3323 }
3324 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3325 return 0, 0, nil
3326}
3327
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303328// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303329func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003330
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003331 f.onuGemInfoLock.Lock()
3332 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003333
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003334 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303335 for idx, onu := range onugem {
3336 if onu.OnuID == onuID {
3337 for _, uni := range onu.UniPorts {
3338 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003339 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 +05303340 return
3341 }
3342 }
3343 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003344 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303345 }
3346 }
npujarec5762e2020-01-01 14:08:48 +05303347 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003348
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303349}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303350
npujarec5762e2020-01-01 14:08:48 +05303351func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3352 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303353 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003354 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303355 return
3356 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003357 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303358 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003359 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303360 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003361 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303362}
Esin Karamanccb714b2019-11-29 15:02:06 +00003363
Girish Gowdra9602eb42020-09-09 15:50:39 -07003364//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3365// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003366func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003367 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003368 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003369 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3370 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3371
Esin Karamanccb714b2019-11-29 15:02:06 +00003372 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003373 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 -07003374 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003375 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003376
3377 var onuID = int32(NoneOnuID)
3378 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003379 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3380 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3381 log.Fields{
3382 "flow": flow,
3383 "device-id": f.deviceHandler.device.Id,
3384 "intf-id": networkInterfaceID,
3385 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003386 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003387 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3388 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3389 log.Fields{
3390 "flow": flowInfo.Flow,
3391 "flow-id": flow.Id,
3392 "device-id": f.deviceHandler.device.Id})
3393 // Remove from device
3394 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3395 // DKB
3396 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3397 log.Fields{
3398 "flow-id": flow.Id,
3399 "error": err})
3400 return err
3401 }
3402 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003403 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003404}
3405
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003406// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3407func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3408 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3409 if err != nil {
3410 _ = olterrors.NewErrNotFound("onu", log.Fields{
3411 "pon-port": f.ponPortIdx}, err).Log()
3412 return
3413 }
3414
3415 f.subscriberDataPathFlowIDMapLock.Lock()
3416 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3417
3418 for _, onu := range onuGemInfo {
3419 for _, uniID := range onu.UniPorts {
3420 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3421 if err != nil {
3422 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3423 }
3424 for _, flowID := range flowIDs {
3425 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3426 if flowInfo == nil {
3427 // Error is already logged in the called function
3428 continue
3429 }
3430 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3431 flowInfo.Flow.FlowType == Downstream &&
3432 flowInfo.Flow.Classifier.OVid > 0 &&
3433 flowInfo.Flow.TechProfileId > 0 {
3434 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3435 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3436 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3437 }
3438 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3439 flowInfo.Flow.FlowType == Upstream &&
3440 flowInfo.Flow.Action.OVid > 0 &&
3441 flowInfo.Flow.TechProfileId > 0 {
3442 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3443 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3444 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3445 }
3446 }
3447 }
3448 }
3449 }
3450}
3451
3452// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3453func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3454 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3455}