blob: 31ca07de863152661a68ae1c9e97c572baca1772 [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
npujarec5762e2020-01-01 14:08:48 +0530443 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(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
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000453 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000454 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 "unsupported": "meter-id",
459 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530460 "meter-id-in-flow": sq.meterID,
461 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000463
Neha Sharma96b7bf22020-06-15 10:37:32 +0000464 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530465 log.Fields{
466 "meter-id": sq.meterID,
467 "direction": Direction,
468 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469
Gamze Abakafee36392019-10-03 11:17:24 +0000470 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000471 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000472 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000475
476 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530477 return olterrors.NewErrNotFound("scheduler-config",
478 log.Fields{
479 "intf-id": sq.intfID,
480 "direction": sq.direction,
481 "tp-inst": sq.tpInst,
482 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000483 }
484
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000486 if sq.flowMetadata != nil {
487 for _, meter := range sq.flowMetadata.Meters {
488 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530491 log.Fields{"meterConfig": meterConfig,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 break
494 }
495 }
496 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 }
499 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530500 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 "reason": "Could-not-get-meterbands-from-flowMetadata",
502 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530503 "meter-id": sq.meterID,
504 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530507 log.Fields{"Bands": meterConfig.Bands,
508 "meter-id": sq.meterID,
509 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530510 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800511 "reason": "Invalid-number-of-bands-in-meter",
512 "meterband-count": len(meterConfig.Bands),
513 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530514 "meter-id": sq.meterID,
515 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
517 cir := meterConfig.Bands[0].Rate
518 cbs := meterConfig.Bands[0].BurstSize
519 eir := meterConfig.Bands[1].Rate
520 ebs := meterConfig.Bands[1].BurstSize
521 pir := cir + eir
522 pbs := cbs + ebs
523 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
524
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700525 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000526 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700528 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530529 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
530 log.Fields{"intf-id": sq.intfID,
531 "direction": sq.direction,
532 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 }
534
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 * store the meter id on the KV store, for further reference.
537 */
npujarec5762e2020-01-01 14:08:48 +0530538 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530539 return olterrors.NewErrAdapter("failed-updating-meter-id",
540 log.Fields{"onu-id": sq.onuID,
541 "meter-id": sq.meterID,
542 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530545 log.Fields{"direction": Direction,
546 "Meter": meterConfig,
547 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 return nil
549}
550
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700551func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000552 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
554 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530555 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
556 log.Fields{"intf-id": sq.intfID,
557 "direction": sq.direction,
558 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
560
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530562 log.Fields{
563 "direction": sq.direction,
564 "TrafficScheds": TrafficSched,
565 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530566 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000567 IntfId: sq.intfID, OnuId: sq.onuID,
568 UniId: sq.uniID, PortNo: sq.uniPort,
569 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000570 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530573 "direction": sq.direction,
574 "traffic-queues": trafficQueues,
575 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576
577 // On receiving the CreateTrafficQueues request, the driver should create corresponding
578 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530580 log.Fields{"direction": sq.direction,
581 "traffic-queues": trafficQueues,
582 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530583 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000584 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
585 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000586 TrafficQueues: trafficQueues,
587 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530588 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000590 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530591 "direction": sq.direction,
592 "traffic-queues": trafficQueues,
593 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000596 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000597 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700598 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000599 //assumed that there is only one queue per PON for the multicast service
600 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
601 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700604 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000605 gemPortID: multicastQueuePerPonPort.GemportId,
606 servicePriority: multicastQueuePerPonPort.Priority,
607 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700608 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000609 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400610 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
611 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
612 return err
613 }
Shrey Baid26912972020-04-16 21:02:31 +0530614
Neha Sharma96b7bf22020-06-15 10:37:32 +0000615 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000616 }
617 }
618 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 return nil
620}
621
salmansiddiqui7ac62132019-08-22 03:58:50 +0000622// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530623func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624
625 var Direction string
626 var SchedCfg *tp_pb.SchedulerConfig
627 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000628 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530629 log.Fields{
630 "direction": sq.direction,
631 "intf-id": sq.intfID,
632 "onu-id": sq.onuID,
633 "uni-id": sq.uniID,
634 "uni-port": sq.uniPort,
635 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000636 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000637 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400638 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000639 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000640 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 Direction = "downstream"
642 }
643
Girish Kumar8f73fe02019-12-09 13:19:37 +0000644 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530645 return olterrors.NewErrNotFound("scheduler-config",
646 log.Fields{
647 "int-id": sq.intfID,
648 "direction": sq.direction,
649 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000650 }
651
npujarec5762e2020-01-01 14:08:48 +0530652 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530654 return olterrors.NewErrNotFound("meter",
655 log.Fields{
656 "onu-id": sq.onuID,
657 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658 }
659 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000660 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530661 log.Fields{
662 "direction": Direction,
663 "intf-id": sq.intfID,
664 "onu-id": sq.onuID,
665 "uni-id": sq.uniID,
666 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400667 return nil
668 }
669 cir := KVStoreMeter.Bands[0].Rate
670 cbs := KVStoreMeter.Bands[0].BurstSize
671 eir := KVStoreMeter.Bands[1].Rate
672 ebs := KVStoreMeter.Bands[1].BurstSize
673 pir := cir + eir
674 pbs := cbs + ebs
675
676 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
677
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700678 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000679 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000680
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000682 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530683 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
684 log.Fields{
685 "intf-id": sq.intfID,
686 "direction": sq.direction,
687 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000688 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689
npujarec5762e2020-01-01 14:08:48 +0530690 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000691 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
692 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000693 TrafficQueues: TrafficQueues,
694 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000695 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530696 log.Fields{
697 "intf-id": sq.intfID,
698 "traffic-queues": TrafficQueues,
699 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530702 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000703 IntfId: sq.intfID, OnuId: sq.onuID,
704 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000706 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530707 log.Fields{
708 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700709 "traffic-schedulers": TrafficSched,
710 "onu-id": sq.onuID,
711 "uni-id": sq.uniID,
712 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400713 }
714
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700715 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
716 log.Fields{"device-id": f.deviceHandler.device.Id,
717 "intf-id": sq.intfID,
718 "onu-id": sq.onuID,
719 "uni-id": sq.uniID,
720 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000721
722 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400723 * delete the meter id on the KV store.
724 */
npujarec5762e2020-01-01 14:08:48 +0530725 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400726 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530727 return olterrors.NewErrAdapter("unable-to-remove-meter",
728 log.Fields{
729 "onu": sq.onuID,
730 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700731 "device-id": f.deviceHandler.device.Id,
732 "intf-id": sq.intfID,
733 "onu-id": sq.onuID,
734 "uni-id": sq.uniID,
735 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000737 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530738 log.Fields{
739 "meter-id": KVStoreMeter.MeterId,
740 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700741 "device-id": f.deviceHandler.device.Id,
742 "intf-id": sq.intfID,
743 "onu-id": sq.onuID,
744 "uni-id": sq.uniID,
745 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400746 return err
747}
748
Gamze Abakafee36392019-10-03 11:17:24 +0000749// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700750func (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 +0000751 var allocIDs []uint32
752 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530753 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530754 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000755 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000756
npujarec5762e2020-01-01 14:08:48 +0530757 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
758 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000759 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530760
Neha Sharma96b7bf22020-06-15 10:37:32 +0000761 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530762 "intf-id": intfID,
763 "onu-id": onuID,
764 "uni-id": uniID,
765 "device-id": f.deviceHandler.device.Id,
766 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530767
Manikkaraj kb1d51442019-07-23 10:41:02 -0400768 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530769 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000770 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530772 log.Fields{
773 "path": tpPath,
774 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530775 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000776 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530777 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530779 log.Fields{
780 "error": err,
781 "tp-id": TpID,
782 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000783 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530784 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400785 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
786 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
787 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530788 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000789 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530790 log.Fields{
791 "uni": uni,
792 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 }
Gamze Abakafee36392019-10-03 11:17:24 +0000795
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700796 switch tpInst := techProfileInstance.(type) {
797 case *tp.TechProfile:
798 if UsMeterID != 0 {
799 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
800 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
801 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700803 log.Fields{
804 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700805 "onu-id": onuID,
806 "uni-id": uniID,
807 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700808 "meter-id": UsMeterID,
809 "device-id": f.deviceHandler.device.Id})
810 return 0, nil, nil
811 }
812 }
813 if DsMeterID != 0 {
814 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
815 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
816 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700818 log.Fields{
819 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700820 "onu-id": onuID,
821 "uni-id": uniID,
822 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700823 "meter-id": DsMeterID,
824 "device-id": f.deviceHandler.device.Id})
825 return 0, nil, nil
826 }
827 }
828 allocID := tpInst.UsScheduler.AllocID
829 for _, gem := range tpInst.UpstreamGemPortAttributeList {
830 gemPortIDs = append(gemPortIDs, gem.GemportID)
831 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700832 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000833
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834 if tpInstanceExists {
835 return allocID, gemPortIDs, techProfileInstance
836 }
837
838 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700839 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700840 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700842 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700843 "intf-id": intfID,
844 "onu-id": onuID,
845 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 "alloc-ids": allocIDs,
847 "gemports": allgemPortIDs,
848 "device-id": f.deviceHandler.device.Id})
849 // Send Tconts and GEM ports to KV store
850 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530851 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 case *tp.EponProfile:
853 // CreateSchedulerQueues for EPON needs to be implemented here
854 // when voltha-protos for EPON is completed.
855 allocID := tpInst.AllocID
856 for _, gem := range tpInst.UpstreamQueueAttributeList {
857 gemPortIDs = append(gemPortIDs, gem.GemportID)
858 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700859 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700860
861 if tpInstanceExists {
862 return allocID, gemPortIDs, techProfileInstance
863 }
864
865 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700866 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700867 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000868 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 log.Fields{
870 "alloc-ids": allocIDs,
871 "gemports": allgemPortIDs,
872 "device-id": f.deviceHandler.device.Id})
873 // Send Tconts and GEM ports to KV store
874 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
875 return allocID, gemPortIDs, techProfileInstance
876 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000877 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 log.Fields{
879 "tpInst": tpInst})
880 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530881 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530882}
883
npujarec5762e2020-01-01 14:08:48 +0530884func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530885
Neha Sharma96b7bf22020-06-15 10:37:32 +0000886 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530887 log.Fields{
888 "intf-id": intfID,
889 "onu-id": onuID,
890 "uni-id": uniID,
891 "alloc-id": allocID,
892 "gemport-ids": gemPortIDs,
893 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530894 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530895 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000896 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 +0530897 }
npujarec5762e2020-01-01 14:08:48 +0530898 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000899 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 +0530900 }
npujarec5762e2020-01-01 14:08:48 +0530901 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000902 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 +0000903 } else {
904 //add to gem to uni cache
905 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530906 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000907 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 -0400908 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530909 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400910 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530911}
912
Esin Karamandf392e12020-12-16 13:33:09 +0000913//addGemPortUniAssociationsToCache
914func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
915 for _, gemPortID := range gemPortIDs {
916 key := gemPortKey{
917 intfID: intfID,
918 gemPort: gemPortID,
919 }
920 f.toGemToUniMap(ctx, key, onuID, uniID)
921 }
922 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
923 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
924}
925
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000927 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530928 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000929 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700930 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400931 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000932 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530933 log.Fields{
934 "intf-id": intfID,
935 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530936 }
937 }
938 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400939 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530940 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530941 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800942 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530943 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
944 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530945 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000946 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530947 log.Fields{
948 "numofTech": tpCount,
949 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
950 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530951 return nil
952}
953
Gamze Abaka7650be62021-02-26 10:50:36 +0000954func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
955 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000956 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530957 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000958 "uplinkClassifier": flowContext.classifier,
959 "uplinkAction": flowContext.action})
960 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530961 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530962}
963
Gamze Abaka7650be62021-02-26 10:50:36 +0000964func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
965 downlinkClassifier := flowContext.classifier
966 downlinkAction := flowContext.action
967
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700968 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000969 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530970 log.Fields{
971 "downlinkClassifier": downlinkClassifier,
972 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400973 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
974 if vlan, exists := downlinkClassifier[VlanVid]; exists {
975 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700976 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000977 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000978 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530979 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000980 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530981 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000982 "onu-id": flowContext.onuID,
983 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800984 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400985 }
986 }
987 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530988 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400989
Manikkaraj k884c1242019-04-11 16:26:42 +0530990 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700991 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400992 // vlan_vid is a uint32. must be type asserted as such or conversion fails
993 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530994 if ok {
995 downlinkAction[VlanVid] = dlClVid & 0xfff
996 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530997 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530998 "reason": "failed-to-convert-vlanid-classifier",
999 "vlan-id": VlanVid,
1000 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301001 }
1002
Gamze Abaka7650be62021-02-26 10:50:36 +00001003 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301004}
1005
Gamze Abaka7650be62021-02-26 10:50:36 +00001006func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001007
1008 var inverseDirection string
1009 if direction == Upstream {
1010 inverseDirection = Downstream
1011 } else {
1012 inverseDirection = Upstream
1013 }
1014
Gamze Abaka7650be62021-02-26 10:50:36 +00001015 intfID := flowContext.intfID
1016 onuID := flowContext.onuID
1017 uniID := flowContext.uniID
1018 classifier := flowContext.classifier
1019 action := flowContext.action
1020 allocID := flowContext.allocID
1021 gemPortID := flowContext.gemPortID
1022 tpID := flowContext.tpID
1023 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301025 log.Fields{
1026 "intf-id": intfID,
1027 "onu-id": onuID,
1028 "uni-id": uniID,
1029 "device-id": f.deviceHandler.device.Id,
1030 "classifier": classifier,
1031 "action": action,
1032 "direction": direction,
1033 "alloc-id": allocID,
1034 "gemport-id": gemPortID,
1035 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001036
1037 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301039 log.Fields{
1040 "device-id": f.deviceHandler.device.Id,
1041 "intf-id": intfID,
1042 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301044 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 classifierProto, err := makeOpenOltClassifierField(classifier)
1046 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301047 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301048 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301050 log.Fields{
1051 "classifier": *classifierProto,
1052 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001053 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001054 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301055 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301056 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001057 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301058 log.Fields{
1059 "action": *actionProto,
1060 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001061 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301062 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301063 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001064 log.Fields{
1065 "classifier": classifier,
1066 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301067 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301069 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001070
1071 // Get symmetric flowID if it exists
1072 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1073 // symmetric flow earlier
1074 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1075 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1076 f.subscriberDataPathFlowIDMapLock.RLock()
1077 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1078 f.subscriberDataPathFlowIDMapLock.RUnlock()
1079
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001080 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001081 OnuId: int32(onuID),
1082 UniId: int32(uniID),
1083 FlowId: logicalFlow.Id,
1084 FlowType: direction,
1085 AllocId: int32(allocID),
1086 NetworkIntfId: int32(networkIntfID),
1087 GemportId: int32(gemPortID),
1088 Classifier: classifierProto,
1089 Action: actionProto,
1090 Priority: int32(logicalFlow.Priority),
1091 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001092 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001093 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001094 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1095 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001096 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001097 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001098 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001100 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301101 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001102 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301103 log.Fields{"direction": direction,
1104 "device-id": f.deviceHandler.device.Id,
1105 "flow": flow,
1106 "intf-id": intfID,
1107 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001108 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1109 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1110 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301111 log.Fields{
1112 "flow": flow,
1113 "device-id": f.deviceHandler.device.Id,
1114 "intf-id": intfID,
1115 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117
1118 // Update the current flowID to the map
1119 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1120 f.subscriberDataPathFlowIDMapLock.Lock()
1121 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1122 f.subscriberDataPathFlowIDMapLock.Unlock()
1123
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301125}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001126
Gamze Abaka7650be62021-02-26 10:50:36 +00001127func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1128
1129 intfID := flowContext.intfID
1130 onuID := flowContext.onuID
1131 uniID := flowContext.uniID
1132 logicalFlow := flowContext.logicalFlow
1133 classifier := flowContext.classifier
1134 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301135
Neha Sharma96b7bf22020-06-15 10:37:32 +00001136 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301137 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301138 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301140 "action": action,
1141 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301143 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144
1145 // Clear the action map
1146 for k := range action {
1147 delete(action, k)
1148 }
1149
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001150 action[TrapToHost] = true
1151 classifier[UDPSrc] = uint32(68)
1152 classifier[UDPDst] = uint32(67)
1153 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301154
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001155 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001156 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301157 log.Fields{
1158 "device-id": f.deviceHandler.device.Id,
1159 "intf-id": intfID,
1160 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001161 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301162 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163
Neha Sharma96b7bf22020-06-15 10:37:32 +00001164 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301165 log.Fields{
1166 "ul_classifier": classifier,
1167 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001168 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301169 "intf-id": intfID,
1170 "onu-id": onuID,
1171 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301172
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 classifierProto, err := makeOpenOltClassifierField(classifier)
1174 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301175 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301176 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001177 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001178 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301180 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301181 }
1182
David K. Bainbridge794735f2020-02-11 21:01:37 -08001183 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184 OnuId: int32(onuID),
1185 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001186 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001187 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001188 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001189 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001190 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301191 Classifier: classifierProto,
1192 Action: actionProto,
1193 Priority: int32(logicalFlow.Priority),
1194 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001195 PortNo: flowContext.portNo,
1196 TechProfileId: flowContext.tpID,
1197 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1198 PbitToGemport: flowContext.pbitToGem,
1199 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001200 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001201 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001202 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001203 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001204 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301205 log.Fields{
1206 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301208 "intf-id": intfID,
1209 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001210 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1211 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 +05301212 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1213 log.Fields{
1214 "flow": dhcpFlow,
1215 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301216 }
1217
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301219}
1220
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001222func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1223 delete(flowContext.classifier, VlanVid)
1224 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225}
1226
1227//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001228func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1229
1230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001255 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001256 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001257 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001258 }
1259
Neha Sharma96b7bf22020-06-15 10:37:32 +00001260 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301261 log.Fields{
1262 "ul_classifier": classifier,
1263 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001264 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301265 "device-id": f.deviceHandler.device.Id,
1266 "intf-id": intfID,
1267 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268
David K. Bainbridge794735f2020-02-11 21:01:37 -08001269 classifierProto, err := makeOpenOltClassifierField(classifier)
1270 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301271 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001272 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301274 log.Fields{
1275 "classifier": *classifierProto,
1276 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001277 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001278 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301279 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001280 }
1281
David K. Bainbridge794735f2020-02-11 21:01:37 -08001282 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283 OnuId: int32(onuID),
1284 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001285 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001286 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001287 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001289 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001290 Classifier: classifierProto,
1291 Action: actionProto,
1292 Priority: int32(logicalFlow.Priority),
1293 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 PortNo: flowContext.portNo,
1295 TechProfileId: flowContext.tpID,
1296 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1297 PbitToGemport: flowContext.pbitToGem,
1298 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001299 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001300
David K. Bainbridge794735f2020-02-11 21:01:37 -08001301 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001302 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 -08001303 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001305 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1306 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 +05301307 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 +00001308 }
1309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001340 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001346 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001347 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301348 "device-id": f.deviceHandler.device.Id,
1349 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001350 "intf-id": intfID,
1351 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301353 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001354 //Add Uplink EthType Flow
1355 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301356 log.Fields{
1357 "ul_classifier": uplinkClassifier,
1358 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001359 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301360 "device-id": f.deviceHandler.device.Id,
1361 "intf-id": intfID,
1362 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301363
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1365 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301366 return olterrors.NewErrInvalidValue(log.Fields{
1367 "classifier": uplinkClassifier,
1368 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001370 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301371 log.Fields{
1372 "classifier": *classifierProto,
1373 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001374 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001375 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301376 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001378 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301379 log.Fields{
1380 "action": *actionProto,
1381 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001382 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301383 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301384 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301386 "action": action,
1387 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301389 }
1390
David K. Bainbridge794735f2020-02-11 21:01:37 -08001391 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001392 OnuId: int32(onuID),
1393 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001394 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001395 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001396 AllocId: int32(allocID),
1397 NetworkIntfId: int32(networkIntfID),
1398 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 Classifier: classifierProto,
1400 Action: actionProto,
1401 Priority: int32(logicalFlow.Priority),
1402 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001403 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001404 TechProfileId: flowContext.tpID,
1405 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1406 PbitToGemport: flowContext.pbitToGem,
1407 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001410 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001411 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001412 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301413 log.Fields{
1414 "device-id": f.deviceHandler.device.Id,
1415 "onu-id": onuID,
1416 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301418 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001419 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1420 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 +05301421 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1422 log.Fields{
1423 "flow": upstreamFlow,
1424 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001426 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301427}
1428
David K. Bainbridge794735f2020-02-11 21:01:37 -08001429func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001430 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431
1432 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1433 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1434 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001435 if vlanID != ReservedVlan {
1436 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001437 classifier.OVid = vid
1438 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301439 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001440 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1441 vid := uint32(metadata)
1442 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001443 classifier.IVid = vid
1444 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301445 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301446 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001447 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301448 classifier.OPbits = vlanPcp
1449 } else {
1450 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301451 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001452 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1453 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1454 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1455 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001456 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001457 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1458 classifier.PktTagType = pktTagType
1459
1460 switch pktTagType {
1461 case SingleTag:
1462 case DoubleTag:
1463 case Untagged:
1464 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001465 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 }
1467 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001468 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301469}
1470
Gamze Abaka724d0852020-03-18 12:10:24 +00001471func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472 var actionCmd openoltpb2.ActionCmd
1473 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001475 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301476 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001477 if _, ok := actionInfo[VlanPcp]; ok {
1478 action.Cmd.RemarkInnerPbits = true
1479 action.IPbits = actionInfo[VlanPcp].(uint32)
1480 if _, ok := actionInfo[VlanVid]; ok {
1481 action.Cmd.TranslateInnerTag = true
1482 action.IVid = actionInfo[VlanVid].(uint32)
1483 }
1484 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001485 } else if _, ok := actionInfo[PushVlan]; ok {
1486 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301487 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001488 if _, ok := actionInfo[VlanPcp]; ok {
1489 action.OPbits = actionInfo[VlanPcp].(uint32)
1490 action.Cmd.RemarkOuterPbits = true
1491 if _, ok := classifierInfo[VlanVid]; ok {
1492 action.IVid = classifierInfo[VlanVid].(uint32)
1493 action.Cmd.TranslateInnerTag = true
1494 }
1495 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496 } else if _, ok := actionInfo[TrapToHost]; ok {
1497 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001499 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301500 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001501 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301502}
1503
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001504// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001505func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1506 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301507}
1508
Gamze Abakafee36392019-10-03 11:17:24 +00001509// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001510func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301511 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001512 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1513
Gamze Abakafee36392019-10-03 11:17:24 +00001514 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301515 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001516 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301517 // return err
1518 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001519 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001520 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001521 }
1522 return nil
1523}
1524
1525// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301526func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001527 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001528 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001529 }
npujarec5762e2020-01-01 14:08:48 +05301530 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301531 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1532 log.Fields{
1533 "tp-id": tpID,
1534 "uni-port-name": uniPortName,
1535 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001536 }
1537 return nil
1538}
1539
David K. Bainbridge794735f2020-02-11 21:01:37 -08001540func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001541
1542 var intfID uint32
1543 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1544 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1545 */
1546 if deviceFlow.AccessIntfId != -1 {
1547 intfID = uint32(deviceFlow.AccessIntfId)
1548 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001549 // We need to log the valid interface ID.
1550 // 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 +00001551 intfID = uint32(deviceFlow.NetworkIntfId)
1552 }
1553
Neha Sharma96b7bf22020-06-15 10:37:32 +00001554 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301555 "flow": *deviceFlow,
1556 "device-id": f.deviceHandler.device.Id,
1557 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001558 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001559
1560 st, _ := status.FromError(err)
1561 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001562 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001563 "err": err,
1564 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301565 "device-id": f.deviceHandler.device.Id,
1566 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001567 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301568 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001569
1570 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301572 log.Fields{"err": err,
1573 "device-flow": deviceFlow,
1574 "device-id": f.deviceHandler.device.Id,
1575 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001576 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001578 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301579 log.Fields{
1580 "flow": *deviceFlow,
1581 "device-id": f.deviceHandler.device.Id,
1582 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001583
1584 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1585 if deviceFlow.AccessIntfId != -1 {
1586 // No need to register the flow if it is a trap on nni flow.
1587 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1588 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1589 return err
1590 }
1591 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001592 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001593}
1594
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1596 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301597 log.Fields{
1598 "flow": *deviceFlow,
1599 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001600 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001601 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001602 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001603 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301604 log.Fields{
1605 "err": err,
1606 "deviceFlow": deviceFlow,
1607 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001608 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001609 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001610 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001611 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001612
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001613 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001615 "of-flow-id": ofFlowID,
1616 "flow": *deviceFlow,
1617 "device-id": f.deviceHandler.device.Id,
1618 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301620}
1621
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001623
1624 classifierInfo := make(map[string]interface{})
1625 actionInfo := make(map[string]interface{})
1626
1627 classifierInfo[EthType] = uint32(LldpEthType)
1628 classifierInfo[PacketTagType] = Untagged
1629 actionInfo[TrapToHost] = true
1630
1631 // LLDP flow is installed to trap LLDP packets on the NNI port.
1632 // We manage flow_id resource pool on per PON port basis.
1633 // Since this situation is tricky, as a hack, we pass the NNI port
1634 // index (network_intf_id) as PON port Index for the flow_id resource
1635 // pool. Also, there is no ONU Id available for trapping LLDP packets
1636 // on NNI port, use onu_id as -1 (invalid)
1637 // ****************** CAVEAT *******************
1638 // This logic works if the NNI Port Id falls within the same valid
1639 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1640 // we need to have a re-look at this.
1641 // *********************************************
1642
1643 var onuID = -1
1644 var uniID = -1
1645 var gemPortID = -1
1646
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301649 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001651 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001652 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001653 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001654 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001655
David K. Bainbridge794735f2020-02-11 21:01:37 -08001656 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1657 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301658 return olterrors.NewErrInvalidValue(
1659 log.Fields{
1660 "classifier": classifierInfo,
1661 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001662 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301664 log.Fields{
1665 "classifier": *classifierProto,
1666 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001667 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301669 return olterrors.NewErrInvalidValue(
1670 log.Fields{
1671 "action": actionInfo,
1672 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001673 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301675 log.Fields{
1676 "action": *actionProto,
1677 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001678
1679 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1680 OnuId: int32(onuID), // OnuId not required
1681 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001682 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001683 FlowType: Downstream,
1684 NetworkIntfId: int32(networkInterfaceID),
1685 GemportId: int32(gemPortID),
1686 Classifier: classifierProto,
1687 Action: actionProto,
1688 Priority: int32(flow.Priority),
1689 Cookie: flow.Cookie,
1690 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001691 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001692 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301693 log.Fields{
1694 "flow": downstreamflow,
1695 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001696 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001697 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301698 log.Fields{
1699 "device-id": f.deviceHandler.device.Id,
1700 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001701 "flow-id": flow.Id})
1702 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1703 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1704 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301705 log.Fields{
1706 "flow": downstreamflow,
1707 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 }
1709 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301710}
1711
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001712func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1713 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001714}
1715
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001716//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001717func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001718 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1719 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1720 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001721 logger.Debugw(ctx, "couldnt-find-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})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001727 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301728 return nil, olterrors.NewErrNotFound("onu-child-device",
1729 log.Fields{
1730 "onu-id": onuID,
1731 "intf-id": intfID,
1732 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001733 }
1734 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1735 //better to ad the device to cache here.
1736 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1737 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301739 log.Fields{
1740 "intf-id": intfID,
1741 "onu-id": onuID,
1742 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001743 }
1744
1745 return onuDev.(*OnuDevice), nil
1746}
1747
1748//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001749func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1750 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301751 log.Fields{
1752 "pon-port": intfID,
1753 "onu-id": onuID,
1754 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001755 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001757 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301758 return nil, olterrors.NewErrNotFound("onu",
1759 log.Fields{
1760 "interface-id": parentPortNo,
1761 "onu-id": onuID,
1762 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001763 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301764 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "device-id": f.deviceHandler.device.Id,
1768 "child_device_id": onuDevice.Id,
1769 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301770 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301771}
1772
Neha Sharma96b7bf22020-06-15 10:37:32 +00001773func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1774 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301775 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "uni-id": uniID,
1781 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001782 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301783 }
1784
1785 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001786 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301787 log.Fields{
1788 "msg": *delGemPortMsg,
1789 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001790 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301791 delGemPortMsg,
1792 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001793 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001794 onuDev.deviceType,
1795 onuDev.deviceID,
1796 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301797 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1798 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001799 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301800 "to-adapter": onuDev.deviceType,
1801 "onu-id": onuDev.deviceID,
1802 "proxyDeviceID": onuDev.proxyDeviceID,
1803 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301804 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001805 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
1807 "msg": delGemPortMsg,
1808 "from-adapter": f.deviceHandler.device.Type,
1809 "to-adapter": onuDev.deviceType,
1810 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301811 return nil
1812}
1813
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1815 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301816 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301818 log.Fields{
1819 "intf-id": intfID,
1820 "onu-id": onuID,
1821 "uni-id": uniID,
1822 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001823 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301824 }
1825
1826 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301828 log.Fields{
1829 "msg": *delTcontMsg,
1830 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001831 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301832 delTcontMsg,
1833 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001834 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001835 onuDev.deviceType,
1836 onuDev.deviceID,
1837 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301838 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1839 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001840 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301841 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1842 "proxyDeviceID": onuDev.proxyDeviceID,
1843 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301844 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001845 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301846 log.Fields{
1847 "msg": delTcontMsg,
1848 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301849 return nil
1850}
1851
Girish Gowdrac3037402020-01-22 20:29:53 +05301852// Once the gemport is released for a given onu, it also has to be cleared from local cache
1853// which was used for deriving the gemport->logicalPortNo during packet-in.
1854// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1855// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001857
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001858 f.onuGemInfoLock.Lock()
1859 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001860
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001863 "gem-port-id": gemPortID,
1864 "intf-id": intfID,
1865 "onu-id": onuID,
1866 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001867 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001868
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001869 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001870deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001871 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301872 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001873 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301874 // If the gemport is found, delete it from local cache.
1875 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001876 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1877 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001878 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301879 log.Fields{
1880 "intf-id": intfID,
1881 "onu-id": onuID,
1882 "deletedgemport-id": gemPortID,
1883 "gemports": onu.GemPorts,
1884 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001885 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301886 }
1887 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001888 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301889 }
1890 }
1891}
1892
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301893//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001894// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301895func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001896 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001897
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001899 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301900 return olterrors.NewErrNotFound("tp-id",
1901 log.Fields{
1902 "flow": flow,
1903 "intf": Intf,
1904 "onu-id": onuID,
1905 "uni-id": uniID,
1906 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001907 }
Gamze Abakafee36392019-10-03 11:17:24 +00001908
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001909 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1910 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1911 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1912 log.Fields{
1913 "tpPath": tpPath,
1914 "device-id": f.deviceHandler.device.Id})
1915 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1916 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1917 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1918 log.Fields{
1919 "tp-id": tpID,
1920 "path": tpPath}, err)
1921 }
1922
1923 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1924
1925 if used {
1926 f.flowsUsedByGemPortKey.Lock()
1927 defer f.flowsUsedByGemPortKey.Unlock()
1928
1929 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1930 for i, flowIDinMap := range flowIDs {
1931 if flowIDinMap == flowID {
1932 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1933 // everytime flowsUsedByGemPort cache is updated the same should be updated
1934 // in kv store by calling UpdateFlowIDsForGem
1935 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1936 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1937 return err
1938 }
1939 break
1940 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001941 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001942 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1943 log.Fields{
1944 "gemport-id": gemPortID,
1945 "usedByFlows": flowIDs,
1946 "device-id": f.deviceHandler.device.Id})
1947 return nil
1948 }
1949 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1950 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1951 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1952 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1953 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Esin Karamandf392e12020-12-16 13:33:09 +00001954 // also clear gem to uni cache
1955 f.removeFromGemToUniMap(gemPortKey{
1956 intfID: Intf,
1957 gemPort: uint32(gemPortID),
1958 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001959 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001960
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001961 f.onuIdsLock.Lock() // TODO: What is this lock?
1962
1963 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1964 // by calling DeleteFlowIDsForGem
1965 f.flowsUsedByGemPortKey.Lock()
1966 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1967 f.flowsUsedByGemPortKey.Unlock()
1968 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1969 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1970
1971 f.onuIdsLock.Unlock()
1972
1973 // Delete the gem port on the ONU.
1974 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1975 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1976 log.Fields{
1977 "err": err,
1978 "intf": Intf,
1979 "onu-id": onuID,
1980 "uni-id": uniID,
1981 "device-id": f.deviceHandler.device.Id,
1982 "gemport-id": gemPortID})
1983 }
1984 switch techprofileInst := techprofileInst.(type) {
1985 case *tp.TechProfile:
1986 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1987 if !ok {
1988 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1989 logger.Warn(ctx, err)
1990 }
1991 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1992 logger.Warn(ctx, err)
1993 }
1994 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
1995 logger.Warn(ctx, err)
1996 }
1997 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
1998 logger.Warn(ctx, err)
1999 }
2000 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
2001 // Delete the TCONT on the ONU.
2002 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
2003 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
2004 log.Fields{
2005 "intf": Intf,
2006 "onu-id": onuID,
2007 "uni-id": uniID,
2008 "device-id": f.deviceHandler.device.Id,
2009 "alloc-id": techprofileInst.UsScheduler.AllocID})
2010 }
2011 }
2012 case *tp.EponProfile:
2013 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2014 logger.Warn(ctx, err)
2015 }
2016 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2017 logger.Warn(ctx, err)
2018 }
2019 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
2020 // Delete the TCONT on the ONU.
2021 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
2022 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302023 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002024 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302025 "onu-id": onuID,
2026 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 "device-id": f.deviceHandler.device.Id,
2028 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00002029 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002030 default:
2031 logger.Errorw(ctx, "error-unknown-tech",
2032 log.Fields{
2033 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002034 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002035
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302036 return nil
2037}
2038
David K. Bainbridge794735f2020-02-11 21:01:37 -08002039// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002040func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002041 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002042 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302043 log.Fields{
2044 "flowDirection": flowDirection,
2045 "flow": *flow,
2046 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002047
2048 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002050 }
2051
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052 classifierInfo := make(map[string]interface{})
2053
Neha Sharma96b7bf22020-06-15 10:37:32 +00002054 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302055 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002056 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002057 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302058 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302059
David K. Bainbridge794735f2020-02-11 21:01:37 -08002060 onuID := int32(onu)
2061 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302062
2063 for _, field := range flows.GetOfbFields(flow) {
2064 if field.Type == flows.IP_PROTO {
2065 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302067 }
2068 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002069 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302070 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002071 "flow-id": flow.Id,
2072 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302073 "onu-id": onuID,
2074 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302075
2076 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2077 onuID = -1
2078 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2080 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002081 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002083 log.Fields{
2084 "port-number": inPort,
2085 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302088 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002089 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2090 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})
2091 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2092 }
2093 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2094 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2095 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2096 return err
2097 }
2098 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2099 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2100 return err
2101 }
2102 if !flowInfo.Flow.ReplicateFlow {
2103 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002104 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 "flow-id": flow.Id,
2106 "stored-flow": flowInfo.Flow,
2107 "device-id": f.deviceHandler.device.Id,
2108 "stored-flow-id": flowInfo.Flow.FlowId,
2109 "onu-id": onuID,
2110 "intf": Intf,
2111 })
2112 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302113 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002114 } else {
2115 gems := make([]uint32, 0)
2116 for _, gem := range flowInfo.Flow.PbitToGemport {
2117 gems = appendUnique32bit(gems, gem)
2118 }
2119 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2120 for _, gem := range gems {
2121 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002122 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002123 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002124 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002125 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002126 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002127 "onu-id": onuID,
2128 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002129 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002130 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002131 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302132 }
2133 }
2134 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002135
2136 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2137 if isDatapathFlow(flow) {
2138 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2139 var inverseDirection string
2140 if flowDirection == Upstream {
2141 inverseDirection = Downstream
2142 } else {
2143 inverseDirection = Upstream
2144 }
2145
2146 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002147 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002148 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002149 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002150 }
2151 }
2152 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002153}
2154
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002155//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002156func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002157
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302159 var direction string
2160 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002161
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302162 for _, action := range flows.GetActions(flow) {
2163 if action.Type == flows.OUTPUT {
2164 if out := action.GetOutput(); out != nil {
2165 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302167 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002169 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002170 }
2171 }
2172 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002173
2174 if flows.HasGroup(flow) {
2175 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002176 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002177 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302178 direction = Upstream
2179 } else {
2180 direction = Downstream
2181 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302182
Girish Gowdracefae192020-03-19 18:14:10 -07002183 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002184 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002185
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002186 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002187}
2188
Esin Karamanae41e2b2019-12-17 18:13:13 +00002189//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2190func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2191 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2192 if ethType, ok := classifierInfo[EthType]; ok {
2193 if ethType.(uint32) == IPv4EthType {
2194 if ipProto, ok := classifierInfo[IPProto]; ok {
2195 if ipProto.(uint32) == IgmpProto {
2196 return true
2197 }
2198 }
2199 }
2200 }
2201 }
2202 return false
2203}
2204
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002205// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2206func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2207 // Step1 : Fill flowControlBlock
2208 // Step2 : Push the flowControlBlock to ONU channel
2209 // Step3 : Wait on response channel for response
2210 // Step4 : Return error value
2211 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2212 errChan := make(chan error)
2213 flowCb := flowControlBlock{
2214 ctx: ctx,
2215 addFlow: addFlow,
2216 flow: flow,
2217 flowMetadata: flowMetadata,
2218 errChan: &errChan,
2219 }
2220 inPort, outPort := getPorts(flow)
2221 var onuID uint32
2222 if inPort != InvalidPort && outPort != InvalidPort {
2223 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2224 }
2225 // inPort or outPort is InvalidPort for trap-from-nni flows.
2226 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2227 // Send the flowCb on the ONU flow channel
2228 f.incomingFlows[onuID] <- flowCb
2229 // Wait on the channel for flow handlers return value
2230 err := <-errChan
2231 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2232 return err
2233}
2234
2235// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2236// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2237func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2238 for {
2239 // block on the channel to receive an incoming flow
2240 // process the flow completely before proceeding to handle the next flow
2241 flowCb := <-subscriberFlowChannel
2242 if flowCb.addFlow {
2243 logger.Debugw(flowCb.ctx, "adding-flow",
2244 log.Fields{"device-id": f.deviceHandler.device.Id,
2245 "flowToAdd": flowCb.flow})
2246 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2247 // Pass the return value over the return channel
2248 *flowCb.errChan <- err
2249 } else {
2250 logger.Debugw(flowCb.ctx, "removing-flow",
2251 log.Fields{"device-id": f.deviceHandler.device.Id,
2252 "flowToRemove": flowCb.flow})
2253 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2254 // Pass the return value over the return channel
2255 *flowCb.errChan <- err
2256 }
2257 }
2258}
2259
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002260// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302261// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002262func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002263 classifierInfo := make(map[string]interface{})
2264 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002265 var UsMeterID uint32
2266 var DsMeterID uint32
2267
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302269 log.Fields{
2270 "flow": flow,
2271 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002272 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002273
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002275 if err != nil {
2276 // Error logging is already done in the called function
2277 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002278 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302279 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002280
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 if flows.HasGroup(flow) {
2282 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002283 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002284 }
2285
manikkaraj k17652a72019-05-06 09:06:36 -04002286 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002288 if err != nil {
2289 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002290 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002291 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002292
Neha Sharma96b7bf22020-06-15 10:37:32 +00002293 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302294 log.Fields{
2295 "classifierinfo_inport": classifierInfo[InPort],
2296 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002297 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002298
Humera Kouser94d7a842019-08-25 19:04:32 -04002299 if ethType, ok := classifierInfo[EthType]; ok {
2300 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002302 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002303 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002304 if ethType.(uint32) == PPPoEDEthType {
2305 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2306 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2307 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2308 }
2309 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002310 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002311 if ipProto, ok := classifierInfo[IPProto]; ok {
2312 if ipProto.(uint32) == IPProtoDhcp {
2313 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302314 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002316 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002317 }
2318 }
2319 }
2320 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002321 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002323 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002324 }
A R Karthick1f85b802019-10-11 05:06:05 +00002325
npujarec5762e2020-01-01 14:08:48 +05302326 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002327
Neha Sharma96b7bf22020-06-15 10:37:32 +00002328 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002329 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302330 return olterrors.NewErrNotFound("tpid-for-flow",
2331 log.Fields{
2332 "flow": flow,
2333 "intf-id": IntfID,
2334 "onu-id": onuID,
2335 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002336 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002337 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302338 log.Fields{
2339 "tp-id": TpID,
2340 "intf-id": intfID,
2341 "onu-id": onuID,
2342 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002343 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002344 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002346 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002347 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002349
2350 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002351 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002352}
Girish Gowdra3d633032019-12-10 16:37:05 +05302353
Esin Karamanccb714b2019-11-29 15:02:06 +00002354// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002355func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002356 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002357 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302358 "classifier-info": classifierInfo,
2359 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002360
Esin Karaman65409d82020-03-18 10:58:18 +00002361 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002362 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002363 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002365
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002366 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002367
David K. Bainbridge794735f2020-02-11 21:01:37 -08002368 onuID := NoneOnuID
2369 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002370
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002371 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002373 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002374 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002375 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2376 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002377 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 }
2379 groupID := actionInfo[GroupID].(uint32)
2380 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002381 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002382 FlowType: Multicast,
2383 NetworkIntfId: int32(networkInterfaceID),
2384 GroupId: groupID,
2385 Classifier: classifierProto,
2386 Priority: int32(flow.Priority),
2387 Cookie: flow.Cookie}
2388
Kent Hagermane6ff1012020-07-14 15:07:53 -04002389 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002390 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002391 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002392 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002393 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002394 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002395 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002396 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002397 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002398 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002399 //cached group can be removed now
2400 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2401 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2402 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002403 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002404
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002405 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2406 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2407 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002408 }
2409 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002410}
2411
Esin Karaman65409d82020-03-18 10:58:18 +00002412//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2413func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2414 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002416 if err != nil {
2417 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2418 }
2419 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002420 }
Esin Karaman65409d82020-03-18 10:58:18 +00002421 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302422 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002423 if e == nil && len(nniPorts) > 0 {
2424 return nniPorts[0], nil
2425 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302426 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002427}
2428
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002429//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002431
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302433 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302435 log.Fields{
2436 "intf-id": intfID,
2437 "onu-id": onuID,
2438 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002439 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302440 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002442
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002444 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002445 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002446 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002447 tpDownloadMsg,
2448 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002449 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002450 onuDev.deviceType,
2451 onuDev.deviceID,
2452 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002453 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302454 return olterrors.NewErrCommunication("send-techprofile-download-request",
2455 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002456 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302457 "to-adapter": onuDev.deviceType,
2458 "onu-id": onuDev.deviceID,
2459 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002460 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002461 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302462 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302463}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002464
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302465//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002466func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302467
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002468 f.onuGemInfoLock.Lock()
2469 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002470 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002471 // If the ONU already exists in onuGemInfo list, nothing to do
2472 for _, onu := range onugem {
2473 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2474 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2475 log.Fields{"onuID": onuID,
2476 "serialNum": serialNum})
2477 return nil
2478 }
2479 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002480
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302481 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002482 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002483 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002484 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302485 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302487 log.Fields{
2488 "intf-id": intfID,
2489 "onu-id": onuID,
2490 "serial-num": serialNum,
2491 "onu": onu,
2492 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002493 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002494}
2495
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302496//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302497func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002498
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002499 f.onuGemInfoLock.Lock()
2500 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002501
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302503 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002504 "gem-port-id": gemPort,
2505 "intf-id": intfID,
2506 "onu-id": onuID,
2507 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002508 "onu-gem": f.onuGemInfo})
2509 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302510 // update the gem to the local cache as well as to kv strore
2511 for idx, onu := range onugem {
2512 if onu.OnuID == onuID {
2513 // check if gem already exists , else update the cache and kvstore
2514 for _, gem := range onu.GemPorts {
2515 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302517 log.Fields{
2518 "gem": gemPort,
2519 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302520 return
2521 }
2522 }
2523 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002524 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002525 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302526 }
2527 }
npujarec5762e2020-01-01 14:08:48 +05302528 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302529 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002530 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302531 log.Fields{
2532 "intf-id": intfID,
2533 "onu-id": onuID,
2534 "gemPort": gemPort,
2535 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002536 return
2537 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002538 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302539 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002540 "gem-port-id": gemPort,
2541 "intf-id": intfID,
2542 "onu-id": onuID,
2543 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002544 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545}
2546
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002547//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302548func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002550 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002551 var err error
2552
2553 if packetIn.IntfType == "pon" {
2554 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002555 // get onu and uni ids associated with the given pon and gem ports
2556 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002557 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558 return logicalPortNum, err
2559 }
Esin Karamandf392e12020-12-16 13:33:09 +00002560 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2561
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002562 if packetIn.PortNo != 0 {
2563 logicalPortNum = packetIn.PortNo
2564 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002565 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002566 }
2567 // 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 +00002568 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002569 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002570 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002571 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002572
2573 if logger.V(log.DebugLevel) {
2574 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2575 log.Fields{
2576 "logical-port-num": logicalPortNum,
2577 "intf-type": packetIn.IntfType,
2578 "packet": hex.EncodeToString(packetIn.Pkt),
2579 })
2580 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581 return logicalPortNum, nil
2582}
2583
Esin Karamandf392e12020-12-16 13:33:09 +00002584//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2585func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2586 key := gemPortKey{
2587 intfID: intfID,
2588 gemPort: gemPortID,
2589 }
2590 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2591 if ok {
2592 if len(uniPortInfo) > 1 {
2593 //return onu ID and uni port from the cache
2594 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2595 log.Fields{
2596 "intfID": intfID,
2597 "gemPortID": gemPortID,
2598 "onuID, uniID": uniPortInfo})
2599 return uniPortInfo[0], uniPortInfo[1], nil
2600 }
2601 }
2602 //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.
2603 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2604 if err == nil {
2605 f.toGemToUniMap(ctx, key, onuID, uniID)
2606 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2607 log.Fields{
2608 "gemPortKey": key,
2609 "onuID": onuID,
2610 "uniID": uniID})
2611 return onuID, uniID, nil
2612 }
2613 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2614 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2615 errors.New("no uni port found"))
2616}
2617
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002618//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002619func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002620 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002621
2622 ctag, priority, err := getCTagFromPacket(ctx, packet)
2623 if err != nil {
2624 return 0, err
2625 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626
Esin Karaman7fb80c22020-07-16 14:23:33 +00002627 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002628 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002629 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002630 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002631 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002633 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302634 log.Fields{
2635 "pktinkey": pktInkey,
2636 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002637
2638 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002639 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302640 //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 +00002641 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302642 if err == nil {
2643 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002644 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302645 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002646 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002647 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302648 log.Fields{
2649 "pktinkey": pktInkey,
2650 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 return gemPortID, nil
2652 }
2653 }
Shrey Baid26912972020-04-16 21:02:31 +05302654 return uint32(0), olterrors.NewErrNotFound("gem-port",
2655 log.Fields{
2656 "pktinkey": pktInkey,
2657 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002658
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659}
2660
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002661func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2662 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002663 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002664 classifier[PacketTagType] = DoubleTag
2665 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666 /* We manage flowId resource pool on per PON port basis.
2667 Since this situation is tricky, as a hack, we pass the NNI port
2668 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002669 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 on NNI port, use onu_id as -1 (invalid)
2671 ****************** CAVEAT *******************
2672 This logic works if the NNI Port Id falls within the same valid
2673 range of PON Port Ids. If this doesn't work for some OLT Vendor
2674 we need to have a re-look at this.
2675 *********************************************
2676 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002677 onuID := -1
2678 uniID := -1
2679 gemPortID := -1
2680 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302682 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302683 return olterrors.NewErrNotFound("nni-intreface-id",
2684 log.Fields{
2685 "classifier": classifier,
2686 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002687 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302688 }
2689
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002690 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002691 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002692 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002693 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002694
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002695 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2696 log.Fields{
2697 "classifier": classifier,
2698 "action": action,
2699 "flowId": logicalFlow.Id,
2700 "intf-id": networkInterfaceID})
2701
David K. Bainbridge794735f2020-02-11 21:01:37 -08002702 classifierProto, err := makeOpenOltClassifierField(classifier)
2703 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002704 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002705 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002707 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002708 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002709 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002710 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002711 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002712 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2713 OnuId: int32(onuID), // OnuId not required
2714 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002715 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002716 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002717 AllocId: int32(allocID), // AllocId not used
2718 NetworkIntfId: int32(networkInterfaceID),
2719 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002720 Classifier: classifierProto,
2721 Action: actionProto,
2722 Priority: int32(logicalFlow.Priority),
2723 Cookie: logicalFlow.Cookie,
2724 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002725 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002726 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002727 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002728 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002729 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2730 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2731 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002732 }
2733 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002734}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002735
Esin Karamanae41e2b2019-12-17 18:13:13 +00002736//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2737func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2738 var packetType string
2739 ovid, ivid := false, false
2740 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2741 vid := vlanID & VlanvIDMask
2742 if vid != ReservedVlan {
2743 ovid = true
2744 }
2745 }
2746 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2747 vid := uint32(metadata)
2748 if vid != ReservedVlan {
2749 ivid = true
2750 }
2751 }
2752 if ovid && ivid {
2753 packetType = DoubleTag
2754 } else if !ovid && !ivid {
2755 packetType = Untagged
2756 } else {
2757 packetType = SingleTag
2758 }
2759 return packetType
2760}
2761
2762//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002763func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002765 action := make(map[string]interface{})
2766 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2767 action[TrapToHost] = true
2768 /* We manage flowId resource pool on per PON port basis.
2769 Since this situation is tricky, as a hack, we pass the NNI port
2770 index (network_intf_id) as PON port Index for the flowId resource
2771 pool. Also, there is no ONU Id available for trapping packets
2772 on NNI port, use onu_id as -1 (invalid)
2773 ****************** CAVEAT *******************
2774 This logic works if the NNI Port Id falls within the same valid
2775 range of PON Port Ids. If this doesn't work for some OLT Vendor
2776 we need to have a re-look at this.
2777 *********************************************
2778 */
2779 onuID := -1
2780 uniID := -1
2781 gemPortID := -1
2782 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002783 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302785 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002786 "classifier": classifier,
2787 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002788 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002789 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002790 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002791 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002792 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002793 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002794
David K. Bainbridge794735f2020-02-11 21:01:37 -08002795 classifierProto, err := makeOpenOltClassifierField(classifier)
2796 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002797 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002798 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002799 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002800 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002801 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002802 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002804 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002805 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2806 OnuId: int32(onuID), // OnuId not required
2807 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002808 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002809 FlowType: Downstream,
2810 AllocId: int32(allocID), // AllocId not used
2811 NetworkIntfId: int32(networkInterfaceID),
2812 GemportId: int32(gemPortID), // GemportId not used
2813 Classifier: classifierProto,
2814 Action: actionProto,
2815 Priority: int32(logicalFlow.Priority),
2816 Cookie: logicalFlow.Cookie,
2817 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002818 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002819 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002820 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002821 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002822 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2823 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2824 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002825 }
2826 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002827}
2828
salmansiddiqui7ac62132019-08-22 03:58:50 +00002829func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2830 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302831 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002832 }
2833 if Dir == tp_pb.Direction_UPSTREAM {
2834 return "upstream", nil
2835 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2836 return "downstream", nil
2837 }
2838 return "", nil
2839}
2840
Kent Hagermane6ff1012020-07-14 15:07:53 -04002841// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302842func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002843 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002844 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002845 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002846 intfID := args[IntfID]
2847 onuID := args[OnuID]
2848 uniID := args[UniID]
2849 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002850 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002852 gemToAes := make(map[uint32]bool)
2853
2854 var attributes []tp.IGemPortAttribute
2855 var direction = tp_pb.Direction_UPSTREAM
2856 switch TpInst := TpInst.(type) {
2857 case *tp.TechProfile:
2858 if IsUpstream(actionInfo[Output].(uint32)) {
2859 attributes = TpInst.UpstreamGemPortAttributeList
2860 } else {
2861 attributes = TpInst.DownstreamGemPortAttributeList
2862 direction = tp_pb.Direction_DOWNSTREAM
2863 }
2864 default:
2865 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2866 return
2867 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868
2869 if len(gemPorts) == 1 {
2870 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 gemPortID = gemPorts[0]
2872 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2874 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 pBitMap := attributes[idx].PbitMap
2876 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2877 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2878 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2879 // this pcp bit traffic.
2880 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2881 if pbitSet == pbit1 {
2882 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2883 pbitToGem[pcp] = gemID
2884 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002885 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002886 }
2887 }
2888 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002889 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2890 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2891 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2892 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002893 }
2894
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2896 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2897
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 if ipProto, ok := classifierInfo[IPProto]; ok {
2899 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002901 "tp-id": tpID,
2902 "alloc-id": allocID,
2903 "intf-id": intfID,
2904 "onu-id": onuID,
2905 "uni-id": uniID,
2906 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002907 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002908 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002909 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 }
2911
Girish Gowdra32625212020-04-29 11:26:35 -07002912 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002913 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302914 log.Fields{
2915 "intf-id": intfID,
2916 "onu-id": onuID,
2917 "uni-id": uniID,
2918 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002920 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002921 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 return
2925 }
2926 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002927 if ethType.(uint32) == EapEthType {
2928 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002929 "intf-id": intfID,
2930 "onu-id": onuID,
2931 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002932 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002933 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002934 var vlanID uint32
2935 if val, ok := classifierInfo[VlanVid]; ok {
2936 vlanID = (val.(uint32)) & VlanvIDMask
2937 } else {
2938 vlanID = DefaultMgmtVlan
2939 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002940 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002941 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002943 } else if ethType.(uint32) == PPPoEDEthType {
2944 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2945 "tp-id": tpID,
2946 "alloc-id": allocID,
2947 "intf-id": intfID,
2948 "onu-id": onuID,
2949 "uni-id": uniID,
2950 })
2951 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002953 logger.Warn(ctx, err)
2954 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002956 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002958 "intf-id": intfID,
2959 "onu-id": onuID,
2960 "uni-id": uniID,
2961 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002962 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002963 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002964 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002966 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002968 "intf-id": intfID,
2969 "onu-id": onuID,
2970 "uni-id": uniID,
2971 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002972 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002973 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002974 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 }
2976 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002977 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302978 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002979 "intf-id": intfID,
2980 "onu-id": onuID,
2981 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302982 "classifier": classifierInfo,
2983 "action": actionInfo,
2984 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002985 return
2986 }
2987 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002988 go func() {
2989 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2990 logger.Warn(ctx, err)
2991 }
2992 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993}
2994
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002995func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2996 f.flowsUsedByGemPortKey.RLock()
2997 flowIDList := f.flowsUsedByGemPort[gemPortID]
2998 f.flowsUsedByGemPortKey.RUnlock()
2999 return len(flowIDList) > 1
3000
Gamze Abakafee36392019-10-03 11:17:24 +00003001}
3002
npujarec5762e2020-01-01 14:08:48 +05303003func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3004 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003005 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3006 for _, currentGemPort := range currentGemPorts {
3007 for _, tpGemPort := range tpGemPorts {
3008 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3009 return true, currentGemPort
3010 }
3011 }
3012 }
Girish Gowdra54934262019-11-13 14:19:55 +05303013 if tpInst.InstanceCtrl.Onu == "single-instance" {
3014 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003015 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003016 logger.Warn(ctx, err)
3017 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003018 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003019 logger.Warn(ctx, err)
3020 }
Girish Gowdra54934262019-11-13 14:19:55 +05303021
3022 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3023 // still be used on other uni ports.
3024 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3025 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003026 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303028 for i := 0; i < len(tpInstances); i++ {
3029 tpI := tpInstances[i]
3030 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303031 for _, tpGemPort := range tpGemPorts {
3032 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303034 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303035 }
3036 }
3037 }
3038 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003040 return false, 0
3041}
3042
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003044 for _, field := range flows.GetOfbFields(flow) {
3045 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003048 } else if field.Type == flows.ETH_DST {
3049 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003054 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303058 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003060 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003063 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003066 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003069 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003072 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003075 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003076 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003078 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 return
3084 }
3085 }
3086}
3087
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003089 for _, action := range flows.GetActions(flow) {
3090 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003092 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003094 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003095 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 }
Scott Baker355d1742019-10-24 10:57:52 -07003097 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003100 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 if out := action.GetPush(); out != nil {
3102 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 } else {
3105 actionInfo[PushVlan] = true
3106 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003107 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303108 log.Fields{
3109 "push-tpid": actionInfo[TPID].(uint32),
3110 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 }
3112 }
Scott Baker355d1742019-10-24 10:57:52 -07003113 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 if out := action.GetSetField(); out != nil {
3115 if field := out.GetField(); field != nil {
3116 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003117 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3120 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 }
3122 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003123 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003125 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003126 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 }
3128 }
3129 return nil
3130}
3131
Neha Sharma96b7bf22020-06-15 10:37:32 +00003132func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003134 fieldtype := ofbField.GetType()
3135 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3137 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003141 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003142 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3143 pcp := ofbField.GetVlanPcp()
3144 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003145 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003146 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003148 }
3149 }
3150}
3151
Neha Sharma96b7bf22020-06-15 10:37:32 +00003152func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003153 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003155 } else {
3156 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003157 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003158 }
3159}
3160
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003162 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003164 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3165 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003166 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003167 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003168 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303169 log.Fields{
3170 "newinport": classifierInfo[InPort].(uint32),
3171 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003172 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303173 return olterrors.NewErrNotFound("child-in-port",
3174 log.Fields{
3175 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3176 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003177 }
3178 }
3179 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003181 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003182 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003183 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003184 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303186 log.Fields{
3187 "newoutport": actionInfo[Output].(uint32),
3188 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003189 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303190 return olterrors.NewErrNotFound("out-port",
3191 log.Fields{
3192 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3193 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003194 }
3195 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3196 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003197 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003198 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303200 log.Fields{
3201 "newinport": actionInfo[Output].(uint32),
3202 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003203 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303204 return olterrors.NewErrNotFound("nni-port",
3205 log.Fields{
3206 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3207 "in-port": classifierInfo[InPort].(uint32),
3208 "out-port": actionInfo[Output].(uint32),
3209 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210 }
3211 }
3212 }
3213 return nil
3214}
Gamze Abakafee36392019-10-03 11:17:24 +00003215
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003217 /* Metadata 8 bytes:
3218 Most Significant 2 Bytes = Inner VLAN
3219 Next 2 Bytes = Tech Profile ID(TPID)
3220 Least Significant 4 Bytes = Port ID
3221 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3222 subscriber related flows.
3223 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003224 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003225 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003226 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003227 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003228 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003229 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003230}
3231
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003232func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3233 for _, sliceElement := range slice {
3234 if sliceElement == item {
3235 return slice
3236 }
3237 }
3238 return append(slice, item)
3239}
3240
3241func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003242 for _, sliceElement := range slice {
3243 if sliceElement == item {
3244 return slice
3245 }
3246 }
3247 return append(slice, item)
3248}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303249
3250// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003251func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303252
3253 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3254 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003256 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003257 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003258 log.Fields{
3259 "port-number": action[Output].(uint32),
3260 "error": err})
3261 return uint32(0), err
3262 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003263 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303264 return intfID, nil
3265 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003266 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003267 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003268 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003269 log.Fields{
3270 "port-number": action[Output].(uint32),
3271 "error": err})
3272 return uint32(0), err
3273 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003274 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303275 return intfID, nil
3276 }
3277 return uint32(0), nil
3278}
3279
3280// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003281func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3282 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3283 if err != nil {
3284 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3285 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3286 return
3287 }
3288 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003289
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003290 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003291 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003292 f.packetInGemPortLock.RUnlock()
3293
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303294 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003295 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003296 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 +05303297 log.Fields{
3298 "pktinkey": pktInkey,
3299 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003300 return
3301 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303302 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003303 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003304 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003305 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003306
npujarec5762e2020-01-01 14:08:48 +05303307 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003308 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 +05303309 log.Fields{
3310 "pktinkey": pktInkey,
3311 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303312}
3313
Esin Karaman7fb80c22020-07-16 14:23:33 +00003314//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3315func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3316 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003317 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003318 return 0, 0, errors.New("invalid packet length")
3319 }
3320 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3321 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3322
3323 var index int8
3324 if outerEthType == 0x8100 {
3325 if innerEthType == 0x8100 {
3326 // q-in-q 802.1ad or 802.1q double tagged packet.
3327 // get the inner vlanId
3328 index = 18
3329 } else {
3330 index = 14
3331 }
3332 priority := (packet[index] >> 5) & 0x7
3333 //13 bits composes vlanId value
3334 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3335 return vlan, priority, nil
3336 }
3337 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3338 return 0, 0, nil
3339}
3340
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303341// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303342func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003343
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003344 f.onuGemInfoLock.Lock()
3345 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003346
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003347 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303348 for idx, onu := range onugem {
3349 if onu.OnuID == onuID {
3350 for _, uni := range onu.UniPorts {
3351 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003352 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 +05303353 return
3354 }
3355 }
3356 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003357 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303358 }
3359 }
npujarec5762e2020-01-01 14:08:48 +05303360 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003361
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303362}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303363
npujarec5762e2020-01-01 14:08:48 +05303364func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3365 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303366 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003367 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303368 return
3369 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003370 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303371 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003372 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303373 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003374 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303375}
Esin Karamanccb714b2019-11-29 15:02:06 +00003376
Girish Gowdra9602eb42020-09-09 15:50:39 -07003377//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3378// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003379func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003380 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003381 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003382 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3383 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3384
Esin Karamanccb714b2019-11-29 15:02:06 +00003385 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003386 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 -07003387 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003388 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003389
3390 var onuID = int32(NoneOnuID)
3391 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003392 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3393 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3394 log.Fields{
3395 "flow": flow,
3396 "device-id": f.deviceHandler.device.Id,
3397 "intf-id": networkInterfaceID,
3398 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003399 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003400 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3401 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3402 log.Fields{
3403 "flow": flowInfo.Flow,
3404 "flow-id": flow.Id,
3405 "device-id": f.deviceHandler.device.Id})
3406 // Remove from device
3407 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3408 // DKB
3409 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3410 log.Fields{
3411 "flow-id": flow.Id,
3412 "error": err})
3413 return err
3414 }
3415 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003416 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003417}
3418
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003419// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3420func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3421 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3422 if err != nil {
3423 _ = olterrors.NewErrNotFound("onu", log.Fields{
3424 "pon-port": f.ponPortIdx}, err).Log()
3425 return
3426 }
3427
3428 f.subscriberDataPathFlowIDMapLock.Lock()
3429 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3430
3431 for _, onu := range onuGemInfo {
3432 for _, uniID := range onu.UniPorts {
3433 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3434 if err != nil {
3435 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3436 }
3437 for _, flowID := range flowIDs {
3438 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3439 if flowInfo == nil {
3440 // Error is already logged in the called function
3441 continue
3442 }
3443 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3444 flowInfo.Flow.FlowType == Downstream &&
3445 flowInfo.Flow.Classifier.OVid > 0 &&
3446 flowInfo.Flow.TechProfileId > 0 {
3447 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3448 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3449 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3450 }
3451 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3452 flowInfo.Flow.FlowType == Upstream &&
3453 flowInfo.Flow.Action.OVid > 0 &&
3454 flowInfo.Flow.TechProfileId > 0 {
3455 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3456 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3457 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3458 }
3459 }
3460 }
3461 }
3462 }
3463}
3464
3465// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3466func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3467 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3468}