blob: 3cc00c72169f6a5fb26506dc617ab0f522d21e51 [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 Abaka01174422021-03-10 06:55:27 +000025 "github.com/opencord/voltha-lib-go/v4/pkg/meters"
Gamze Abaka7650be62021-02-26 10:50:36 +000026 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030027 "strings"
28 "sync"
29
Girish Gowdraa09aeab2020-09-14 16:30:52 -070030 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
31 "github.com/opencord/voltha-lib-go/v4/pkg/log"
32 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080033 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070034 "github.com/opencord/voltha-protos/v4/go/common"
35 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
37 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
38 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
39 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040040
Thomas Lee S94109f12020-03-03 16:39:29 +053041 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000042 "google.golang.org/grpc/codes"
43 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053044)
45
46const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070047 //IPProtoDhcp flow category
48 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053049
Girish Gowdraa09aeab2020-09-14 16:30:52 -070050 //IgmpProto proto value
51 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070052
53 //EapEthType eapethtype value
54 EapEthType = 0x888e
55 //LldpEthType lldp ethtype value
56 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000057 //IPv4EthType IPv4 ethernet type value
58 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030059 //PPPoEDEthType PPPoE discovery ethernet type value
60 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061
Andrea Campanella7acc0b92020-02-14 09:20:49 +010062 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
63 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065 //DefaultMgmtVlan default vlan value
66 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053067
manikkaraj kbf256be2019-03-25 00:13:48 +053068 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069
David K. Bainbridge82efc492019-09-04 09:57:11 -070070 //Upstream constant
71 Upstream = "upstream"
72 //Downstream constant
73 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000074 //Multicast constant
75 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //PacketTagType constant
77 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070078 //Untagged constant
79 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080 //SingleTag constant
81 SingleTag = "single_tag"
82 //DoubleTag constant
83 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053084
85 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086
87 //EthType constant
88 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000089 //EthDst constant
90 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091 //TPID constant
92 TPID = "tpid"
93 //IPProto constant
94 IPProto = "ip_proto"
95 //InPort constant
96 InPort = "in_port"
97 //VlanVid constant
98 VlanVid = "vlan_vid"
99 //VlanPcp constant
100 VlanPcp = "vlan_pcp"
101
102 //UDPDst constant
103 UDPDst = "udp_dst"
104 //UDPSrc constant
105 UDPSrc = "udp_src"
106 //Ipv4Dst constant
107 Ipv4Dst = "ipv4_dst"
108 //Ipv4Src constant
109 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Metadata constant
111 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 //TunnelID constant
113 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700114 //Output constant
115 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000116 //GroupID constant
117 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700118 // Actions
119
120 //PopVlan constant
121 PopVlan = "pop_vlan"
122 //PushVlan constant
123 PushVlan = "push_vlan"
124 //TrapToHost constant
125 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400126 //MaxMeterBand constant
127 MaxMeterBand = 2
128 //VlanPCPMask contant
129 VlanPCPMask = 0xFF
130 //VlanvIDMask constant
131 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000132 //IntfID constant
133 IntfID = "intfId"
134 //OnuID constant
135 OnuID = "onuId"
136 //UniID constant
137 UniID = "uniId"
138 //PortNo constant
139 PortNo = "portNo"
140 //AllocID constant
141 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000142 //GemID constant
143 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000144
145 //NoneOnuID constant
146 NoneOnuID = -1
147 //NoneUniID constant
148 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700149
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700150 // Max number of flows that can be queued per ONU
151 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530152
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700153 bitMapPrefix = "0b"
154 pbit1 = '1'
155)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400156
Esin Karamandf392e12020-12-16 13:33:09 +0000157type gemPortKey struct {
158 intfID uint32
159 gemPort uint32
160}
161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
163 direction tp_pb.Direction
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 tpID uint32
168 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700169 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000170 meterID uint32
171 flowMetadata *voltha.FlowMetadata
172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 portNo uint32
179 classifier map[string]interface{}
180 action map[string]interface{}
181 logicalFlow *ofp.OfpFlowStats
182 allocID uint32
183 gemPortID uint32
184 tpID uint32
185 pbitToGem map[uint32]uint32
186 gemToAes map[uint32]bool
187}
188
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700189// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
190type subscriberDataPathFlowIDKey struct {
191 intfID uint32
192 onuID uint32
193 uniID uint32
194 direction string
195 tpID uint32
196}
197
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700198// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
199// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
200// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
201// flow and processes it serially
202type flowControlBlock struct {
203 ctx context.Context // Flow handler context
204 addFlow bool // if true flow to be added, else removed
205 flow *voltha.OfpFlowStats // Flow message
206 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
207 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000208}
209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530211type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700212 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
213 techprofile map[uint32]tp.TechProfileIf
214 deviceHandler *DeviceHandler
215 grpMgr *OpenOltGroupMgr
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
217
218 onuIdsLock sync.RWMutex // TODO: Do we need this?
219
220 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
221 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
222
223 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
224 packetInGemPortLock sync.RWMutex
225
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700226 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700227 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700228 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700229 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700231 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
232 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
233 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
234 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700235
236 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
237 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
238 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000239
240 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
241 gemToUniMap map[gemPortKey][]uint32
242 //We need to have a global lock on the gemToUniLock map
243 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530244}
245
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700246//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700247func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000248 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530249 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530250 var err error
251 var idx uint32
252
manikkaraj kbf256be2019-03-25 00:13:48 +0530253 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700254 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000256 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000257 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
258 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 return nil
260 }
William Kurkian740a09c2019-10-23 17:07:38 -0400261 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700265 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700266 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
267 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700268
269 // Create a slice of buffered channels for handling concurrent flows per ONU.
270 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
271 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
272 for i := range flowMgr.incomingFlows {
273 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
274 // Spin up a go routine to handling incoming flows (add/remove).
275 // There will be on go routine per ONU.
276 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
277 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
278 }
279
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530280 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700281 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
282 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 //Load flowID list per gem map per interface from the kvstore.
285 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000286 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000287
288 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
289 flowMgr.gemToUniLock = sync.RWMutex{}
290
Girish Gowdra9602eb42020-09-09 15:50:39 -0700291 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700292 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000293 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530294 return &flowMgr
295}
296
Esin Karamandf392e12020-12-16 13:33:09 +0000297// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
298func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
299 f.gemToUniLock.Lock()
300 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
301 f.gemToUniLock.Unlock()
302}
303
304// fromGemToUniMap returns onu and uni ID associated with the given key
305func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
306 f.gemToUniLock.RLock()
307 defer f.gemToUniLock.RUnlock()
308 val, ok := f.gemToUniMap[key]
309 return val, ok
310}
311
312// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
313func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
314 f.gemToUniLock.Lock()
315 defer f.gemToUniLock.Unlock()
316 delete(f.gemToUniMap, key)
317}
318
Kent Hagermane6ff1012020-07-14 15:07:53 -0400319func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700320 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
321 // Flow is not replicated in this case, we need to register the flow for a single gem-port
322 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
323 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
324 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
325 for _, gemPort := range deviceFlow.PbitToGemport {
326 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
327 return err
328 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700329 }
Gamze Abakafee36392019-10-03 11:17:24 +0000330 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700331 return nil
332}
333
334func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
335 f.flowsUsedByGemPortKey.Lock()
336 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
337 if !ok {
338 flowIDList = []uint64{flowFromCore.Id}
339 }
340 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
341 f.flowsUsedByGemPort[gemPortID] = flowIDList
342 f.flowsUsedByGemPortKey.Unlock()
343
344 // update the flowids for a gem to the KVstore
345 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400346}
347
Girish Gowdra9602eb42020-09-09 15:50:39 -0700348func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200350 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000351 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700353 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530354
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "device-id": f.deviceHandler.device.Id,
357 "intf-id": intfID,
358 "onu-id": onuID,
359 "uni-id": uniID,
360 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700361 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530362 "action": actionInfo,
363 "usmeter-iD": UsMeterID,
364 "dsmeter-iD": DsMeterID,
365 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400366 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
367 // is because the flow is an NNI flow and there would be no onu resources associated with it
368 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400369 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200370 cause := "no-onu-id-for-flow"
371 fields := log.Fields{
372 "onu": onuID,
373 "port-no": portNo,
374 "classifer": classifierInfo,
375 "action": actionInfo,
376 "device-id": f.deviceHandler.device.Id}
377 logger.Errorw(ctx, cause, fields)
378 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530379 }
380
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700381 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000382 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530383 "uni": uni,
384 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530385
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700386 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
387 "device-id": f.deviceHandler.device.Id,
388 "intf-id": intfID,
389 "onu-id": onuID,
390 "uni-id": uniID,
391 "port-no": portNo,
392 "classifier": classifierInfo,
393 "action": actionInfo,
394 "usmeter-id": UsMeterID,
395 "dsmeter-id": DsMeterID,
396 "tp-id": TpID})
397 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
398 if allocID == 0 || gemPorts == nil || TpInst == nil {
399 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
400 return olterrors.NewErrNotFound(
401 "alloc-id-gem-ports-tp-unavailable",
402 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700404 args := make(map[string]uint32)
405 args[IntfID] = intfID
406 args[OnuID] = onuID
407 args[UniID] = uniID
408 args[PortNo] = portNo
409 args[AllocID] = allocID
410
411 /* Flows can be added specific to gemport if p-bits are received.
412 * If no pbit mentioned then adding flows for all gemports
413 */
414 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
415
Andrea Campanellabfe08432020-09-11 17:07:03 +0200416 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530417}
418
salmansiddiqui7ac62132019-08-22 03:58:50 +0000419// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530420func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421
Neha Sharma96b7bf22020-06-15 10:37:32 +0000422 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530423 log.Fields{"dir": sq.direction,
424 "intf-id": sq.intfID,
425 "onu-id": sq.onuID,
426 "uni-id": sq.uniID,
427 "tp-id": sq.tpID,
428 "meter-id": sq.meterID,
429 "tp-inst": sq.tpInst,
430 "flowmetadata": sq.flowMetadata,
431 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432
Gamze Abakafee36392019-10-03 11:17:24 +0000433 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 if err != nil {
435 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
437
438 /* Lets make a simple assumption that if the meter-id is present on the KV store,
439 * then the scheduler and queues configuration is applied on the OLT device
440 * in the given direction.
441 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000442
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700444 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530446 return olterrors.NewErrNotFound("meter",
447 log.Fields{"intf-id": sq.intfID,
448 "onu-id": sq.onuID,
449 "uni-id": sq.uniID,
450 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000452
Girish Gowdraa482f272021-03-24 23:04:19 -0700453 if meterInfo != nil {
454 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
455 if meterInfo.MeterConfig.MeterId == sq.meterID {
456 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
457 return err
458 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530461 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 "unsupported": "meter-id",
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 "kv-store-meter-id": meterInfo.MeterConfig.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "meter-id-in-flow": sq.meterID,
465 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000467
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530469 log.Fields{
470 "meter-id": sq.meterID,
471 "direction": Direction,
472 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000473
Gamze Abakafee36392019-10-03 11:17:24 +0000474 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000476 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000477 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000479
480 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530481 return olterrors.NewErrNotFound("scheduler-config",
482 log.Fields{
483 "intf-id": sq.intfID,
484 "direction": sq.direction,
485 "tp-inst": sq.tpInst,
486 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000487 }
488
Girish Gowdraa482f272021-03-24 23:04:19 -0700489 found := false
490 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000491 if sq.flowMetadata != nil {
492 for _, meter := range sq.flowMetadata.Meters {
493 if sq.meterID == meter.MeterId {
Girish Gowdraa482f272021-03-24 23:04:19 -0700494 meterInfo.MeterConfig = ofp.OfpMeterConfig{}
495 meterInfo.MeterConfig.MeterId = meter.MeterId
496 meterInfo.MeterConfig.Flags = meter.Flags
497 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
498 meterInfo.MeterConfig.Bands = append(meterInfo.MeterConfig.Bands, meter.Bands...)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000499 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 log.Fields{"meterConfig": meterInfo.MeterConfig,
Shrey Baid26912972020-04-16 21:02:31 +0530501 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700502 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 break
504 }
505 }
506 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700509 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530510 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800511 "reason": "Could-not-get-meterbands-from-flowMetadata",
512 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530513 "meter-id": sq.meterID,
514 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400515 }
Gamze Abaka01174422021-03-10 06:55:27 +0000516
517 var TrafficShaping *tp_pb.TrafficShapingInfo
518 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, &meterInfo.MeterConfig); err != nil {
519 return olterrors.NewErrInvalidValue(log.Fields{
520 "reason": "invalid-meter-config",
521 "meter-id": sq.meterID,
522 "device-id": f.deviceHandler.device.Id}, nil)
523 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400524
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 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700538 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +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,
Girish Gowdraa482f272021-03-24 23:04:19 -0700546 "meter-info": meterInfo,
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
Girish Gowdraa482f272021-03-24 23:04:19 -0700652 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700654 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000655 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000656
Neha Sharma96b7bf22020-06-15 10:37:32 +0000657 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000658 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530659 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
660 log.Fields{
661 "intf-id": sq.intfID,
662 "direction": sq.direction,
663 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665
npujarec5762e2020-01-01 14:08:48 +0530666 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000667 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
668 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000669 TrafficQueues: TrafficQueues,
670 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000671 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530672 log.Fields{
673 "intf-id": sq.intfID,
674 "traffic-queues": TrafficQueues,
675 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000677 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530678 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000679 IntfId: sq.intfID, OnuId: sq.onuID,
680 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000682 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
684 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "traffic-schedulers": TrafficSched,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 }
690
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700691 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
692 log.Fields{"device-id": f.deviceHandler.device.Id,
693 "intf-id": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000697
698 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699 * delete the meter id on the KV store.
700 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700701 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530703 return olterrors.NewErrAdapter("unable-to-remove-meter",
704 log.Fields{
705 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700706 "device-id": f.deviceHandler.device.Id,
707 "intf-id": sq.intfID,
708 "onu-id": sq.onuID,
709 "uni-id": sq.uniID,
710 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000712 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530713 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530714 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700715 "device-id": f.deviceHandler.device.Id,
716 "intf-id": sq.intfID,
717 "onu-id": sq.onuID,
718 "uni-id": sq.uniID,
719 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400720 return err
721}
722
Gamze Abakafee36392019-10-03 11:17:24 +0000723// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700724func (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 +0000725 var allocIDs []uint32
726 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530728 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000729 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000730
npujarec5762e2020-01-01 14:08:48 +0530731 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
732 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530734
Neha Sharma96b7bf22020-06-15 10:37:32 +0000735 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530736 "intf-id": intfID,
737 "onu-id": onuID,
738 "uni-id": uniID,
739 "device-id": f.deviceHandler.device.Id,
740 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530741
Manikkaraj kb1d51442019-07-23 10:41:02 -0400742 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530743 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000744 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000745 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530746 log.Fields{
747 "path": tpPath,
748 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530749 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000750 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530751 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000752 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530753 log.Fields{
754 "error": err,
755 "tp-id": TpID,
756 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000757 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530758 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400759 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
760 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
761 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530762 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000763 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530764 log.Fields{
765 "uni": uni,
766 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530767 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530768 }
Gamze Abakafee36392019-10-03 11:17:24 +0000769
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700770 switch tpInst := techProfileInstance.(type) {
771 case *tp.TechProfile:
772 if UsMeterID != 0 {
773 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
774 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
775 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700777 log.Fields{
778 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700779 "onu-id": onuID,
780 "uni-id": uniID,
781 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700782 "meter-id": UsMeterID,
783 "device-id": f.deviceHandler.device.Id})
784 return 0, nil, nil
785 }
786 }
787 if DsMeterID != 0 {
788 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
789 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
790 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000791 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700792 log.Fields{
793 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700794 "onu-id": onuID,
795 "uni-id": uniID,
796 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700797 "meter-id": DsMeterID,
798 "device-id": f.deviceHandler.device.Id})
799 return 0, nil, nil
800 }
801 }
802 allocID := tpInst.UsScheduler.AllocID
803 for _, gem := range tpInst.UpstreamGemPortAttributeList {
804 gemPortIDs = append(gemPortIDs, gem.GemportID)
805 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700806 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000807
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700808 if tpInstanceExists {
809 return allocID, gemPortIDs, techProfileInstance
810 }
811
812 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700813 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700814 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700816 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700817 "intf-id": intfID,
818 "onu-id": onuID,
819 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 "alloc-ids": allocIDs,
821 "gemports": allgemPortIDs,
822 "device-id": f.deviceHandler.device.Id})
823 // Send Tconts and GEM ports to KV store
824 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530825 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700826 case *tp.EponProfile:
827 // CreateSchedulerQueues for EPON needs to be implemented here
828 // when voltha-protos for EPON is completed.
829 allocID := tpInst.AllocID
830 for _, gem := range tpInst.UpstreamQueueAttributeList {
831 gemPortIDs = append(gemPortIDs, gem.GemportID)
832 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700833 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834
835 if tpInstanceExists {
836 return allocID, gemPortIDs, techProfileInstance
837 }
838
839 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700840 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 log.Fields{
844 "alloc-ids": allocIDs,
845 "gemports": allgemPortIDs,
846 "device-id": f.deviceHandler.device.Id})
847 // Send Tconts and GEM ports to KV store
848 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
849 return allocID, gemPortIDs, techProfileInstance
850 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 log.Fields{
853 "tpInst": tpInst})
854 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530855 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530856}
857
npujarec5762e2020-01-01 14:08:48 +0530858func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530859
Neha Sharma96b7bf22020-06-15 10:37:32 +0000860 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530861 log.Fields{
862 "intf-id": intfID,
863 "onu-id": onuID,
864 "uni-id": uniID,
865 "alloc-id": allocID,
866 "gemport-ids": gemPortIDs,
867 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530868 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530869 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 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 +0530871 }
npujarec5762e2020-01-01 14:08:48 +0530872 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000873 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 +0530874 }
npujarec5762e2020-01-01 14:08:48 +0530875 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 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 +0000877 } else {
878 //add to gem to uni cache
879 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 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 -0400882 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530883 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400884 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530885}
886
Esin Karamandf392e12020-12-16 13:33:09 +0000887//addGemPortUniAssociationsToCache
888func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
889 for _, gemPortID := range gemPortIDs {
890 key := gemPortKey{
891 intfID: intfID,
892 gemPort: gemPortID,
893 }
894 f.toGemToUniMap(ctx, key, onuID, uniID)
895 }
896 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
897 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
898}
899
Neha Sharma96b7bf22020-06-15 10:37:32 +0000900func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000901 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530902 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000903 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400905 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530907 log.Fields{
908 "intf-id": intfID,
909 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530910 }
911 }
912 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530914 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530915 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800916 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530917 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
918 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000920 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530921 log.Fields{
922 "numofTech": tpCount,
923 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
924 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530925 return nil
926}
927
Gamze Abaka7650be62021-02-26 10:50:36 +0000928func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
929 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530931 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000932 "uplinkClassifier": flowContext.classifier,
933 "uplinkAction": flowContext.action})
934 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530935 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530936}
937
Gamze Abaka7650be62021-02-26 10:50:36 +0000938func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
939 downlinkClassifier := flowContext.classifier
940 downlinkAction := flowContext.action
941
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530944 log.Fields{
945 "downlinkClassifier": downlinkClassifier,
946 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400947 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
948 if vlan, exists := downlinkClassifier[VlanVid]; exists {
949 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700950 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000951 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000954 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530955 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000956 "onu-id": flowContext.onuID,
957 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800958 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400959 }
960 }
961 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530962 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400963
Manikkaraj k884c1242019-04-11 16:26:42 +0530964 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400966 // vlan_vid is a uint32. must be type asserted as such or conversion fails
967 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530968 if ok {
969 downlinkAction[VlanVid] = dlClVid & 0xfff
970 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530971 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530972 "reason": "failed-to-convert-vlanid-classifier",
973 "vlan-id": VlanVid,
974 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530975 }
976
Gamze Abaka7650be62021-02-26 10:50:36 +0000977 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530978}
979
Gamze Abaka7650be62021-02-26 10:50:36 +0000980func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700981
982 var inverseDirection string
983 if direction == Upstream {
984 inverseDirection = Downstream
985 } else {
986 inverseDirection = Upstream
987 }
988
Gamze Abaka7650be62021-02-26 10:50:36 +0000989 intfID := flowContext.intfID
990 onuID := flowContext.onuID
991 uniID := flowContext.uniID
992 classifier := flowContext.classifier
993 action := flowContext.action
994 allocID := flowContext.allocID
995 gemPortID := flowContext.gemPortID
996 tpID := flowContext.tpID
997 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
1000 "intf-id": intfID,
1001 "onu-id": onuID,
1002 "uni-id": uniID,
1003 "device-id": f.deviceHandler.device.Id,
1004 "classifier": classifier,
1005 "action": action,
1006 "direction": direction,
1007 "alloc-id": allocID,
1008 "gemport-id": gemPortID,
1009 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001010
1011 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301013 log.Fields{
1014 "device-id": f.deviceHandler.device.Id,
1015 "intf-id": intfID,
1016 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301018 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 classifierProto, err := makeOpenOltClassifierField(classifier)
1020 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301021 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301022 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301024 log.Fields{
1025 "classifier": *classifierProto,
1026 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001027 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301029 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301030 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301032 log.Fields{
1033 "action": *actionProto,
1034 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301036 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301037 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 log.Fields{
1039 "classifier": classifier,
1040 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301041 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301043 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001044
1045 // Get symmetric flowID if it exists
1046 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1047 // symmetric flow earlier
1048 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1049 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1050 f.subscriberDataPathFlowIDMapLock.RLock()
1051 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1052 f.subscriberDataPathFlowIDMapLock.RUnlock()
1053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001054 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001055 OnuId: int32(onuID),
1056 UniId: int32(uniID),
1057 FlowId: logicalFlow.Id,
1058 FlowType: direction,
1059 AllocId: int32(allocID),
1060 NetworkIntfId: int32(networkIntfID),
1061 GemportId: int32(gemPortID),
1062 Classifier: classifierProto,
1063 Action: actionProto,
1064 Priority: int32(logicalFlow.Priority),
1065 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001066 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001067 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001068 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1069 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001070 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001071 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001072 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001074 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{"direction": direction,
1078 "device-id": f.deviceHandler.device.Id,
1079 "flow": flow,
1080 "intf-id": intfID,
1081 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001082 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1083 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1084 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "flow": flow,
1087 "device-id": f.deviceHandler.device.Id,
1088 "intf-id": intfID,
1089 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001091
1092 // Update the current flowID to the map
1093 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1094 f.subscriberDataPathFlowIDMapLock.Lock()
1095 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1096 f.subscriberDataPathFlowIDMapLock.Unlock()
1097
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301099}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001100
Gamze Abaka7650be62021-02-26 10:50:36 +00001101func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1102
1103 intfID := flowContext.intfID
1104 onuID := flowContext.onuID
1105 uniID := flowContext.uniID
1106 logicalFlow := flowContext.logicalFlow
1107 classifier := flowContext.classifier
1108 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109
Neha Sharma96b7bf22020-06-15 10:37:32 +00001110 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301111 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301112 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301114 "action": action,
1115 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301117 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118
1119 // Clear the action map
1120 for k := range action {
1121 delete(action, k)
1122 }
1123
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001124 action[TrapToHost] = true
1125 classifier[UDPSrc] = uint32(68)
1126 classifier[UDPDst] = uint32(67)
1127 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301128
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001129 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301131 log.Fields{
1132 "device-id": f.deviceHandler.device.Id,
1133 "intf-id": intfID,
1134 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301136 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301139 log.Fields{
1140 "ul_classifier": classifier,
1141 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001142 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301143 "intf-id": intfID,
1144 "onu-id": onuID,
1145 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 classifierProto, err := makeOpenOltClassifierField(classifier)
1148 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301149 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001152 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301154 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301155 }
1156
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 OnuId: int32(onuID),
1159 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001160 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001161 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001162 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001164 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301165 Classifier: classifierProto,
1166 Action: actionProto,
1167 Priority: int32(logicalFlow.Priority),
1168 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001169 PortNo: flowContext.portNo,
1170 TechProfileId: flowContext.tpID,
1171 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1172 PbitToGemport: flowContext.pbitToGem,
1173 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001174 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001176 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301179 log.Fields{
1180 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001181 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301182 "intf-id": intfID,
1183 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001184 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1185 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 +05301186 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1187 log.Fields{
1188 "flow": dhcpFlow,
1189 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301190 }
1191
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301193}
1194
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001196func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1197 delete(flowContext.classifier, VlanVid)
1198 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001199}
1200
1201//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001202func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1203
1204 intfID := flowContext.intfID
1205 onuID := flowContext.onuID
1206 uniID := flowContext.uniID
1207 logicalFlow := flowContext.logicalFlow
1208 classifier := flowContext.classifier
1209 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001210
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001212 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301213 return olterrors.NewErrNotFound("nni-interface-id",
1214 log.Fields{
1215 "classifier": classifier,
1216 "action": action,
1217 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219 }
1220
1221 // Clear the action map
1222 for k := range action {
1223 delete(action, k)
1224 }
1225
1226 action[TrapToHost] = true
1227 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001228
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001229 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001230 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232 }
1233
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301235 log.Fields{
1236 "ul_classifier": classifier,
1237 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001238 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301239 "device-id": f.deviceHandler.device.Id,
1240 "intf-id": intfID,
1241 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 classifierProto, err := makeOpenOltClassifierField(classifier)
1244 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301245 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001246 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301248 log.Fields{
1249 "classifier": *classifierProto,
1250 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001251 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301253 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 }
1255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257 OnuId: int32(onuID),
1258 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001259 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001261 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001263 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 Classifier: classifierProto,
1265 Action: actionProto,
1266 Priority: int32(logicalFlow.Priority),
1267 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001268 PortNo: flowContext.portNo,
1269 TechProfileId: flowContext.tpID,
1270 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1271 PbitToGemport: flowContext.pbitToGem,
1272 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001273 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001276 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 -08001277 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001278
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001279 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1280 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 +05301281 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 +00001282 }
1283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285}
1286
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001287// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001288func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1289 intfID := flowContext.intfID
1290 onuID := flowContext.onuID
1291 uniID := flowContext.uniID
1292 portNo := flowContext.portNo
1293 allocID := flowContext.allocID
1294 gemPortID := flowContext.gemPortID
1295 logicalFlow := flowContext.logicalFlow
1296 classifier := flowContext.classifier
1297 action := flowContext.action
1298
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001299 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301300 log.Fields{
1301 "intf-id": intfID,
1302 "onu-id": onuID,
1303 "port-no": portNo,
1304 "alloc-id": allocID,
1305 "gemport-id": gemPortID,
1306 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001307 "flow": logicalFlow,
1308 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301309
1310 uplinkClassifier := make(map[string]interface{})
1311 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301312
manikkaraj kbf256be2019-03-25 00:13:48 +05301313 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001314 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 uplinkClassifier[PacketTagType] = SingleTag
1316 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001317 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301322 "device-id": f.deviceHandler.device.Id,
1323 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 "intf-id": intfID,
1325 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301327 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001328 //Add Uplink EthType Flow
1329 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301330 log.Fields{
1331 "ul_classifier": uplinkClassifier,
1332 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001333 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301334 "device-id": f.deviceHandler.device.Id,
1335 "intf-id": intfID,
1336 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1339 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301340 return olterrors.NewErrInvalidValue(log.Fields{
1341 "classifier": uplinkClassifier,
1342 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301345 log.Fields{
1346 "classifier": *classifierProto,
1347 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001348 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301350 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "action": *actionProto,
1355 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301357 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301358 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301360 "action": action,
1361 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 }
1364
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 OnuId: int32(onuID),
1367 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001368 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001369 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 AllocId: int32(allocID),
1371 NetworkIntfId: int32(networkIntfID),
1372 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 Classifier: classifierProto,
1374 Action: actionProto,
1375 Priority: int32(logicalFlow.Priority),
1376 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001377 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001378 TechProfileId: flowContext.tpID,
1379 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1380 PbitToGemport: flowContext.pbitToGem,
1381 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001384 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001386 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301387 log.Fields{
1388 "device-id": f.deviceHandler.device.Id,
1389 "onu-id": onuID,
1390 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001391 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301392 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001393 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1394 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 +05301395 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1396 log.Fields{
1397 "flow": upstreamFlow,
1398 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
David K. Bainbridge794735f2020-02-11 21:01:37 -08001403func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405
1406 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1407 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1408 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001409 if vlanID != ReservedVlan {
1410 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001411 classifier.OVid = vid
1412 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1415 vid := uint32(metadata)
1416 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001417 classifier.IVid = vid
1418 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301419 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301420 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001421 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301422 classifier.OPbits = vlanPcp
1423 } else {
1424 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001426 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1427 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1428 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1429 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001430 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1432 classifier.PktTagType = pktTagType
1433
1434 switch pktTagType {
1435 case SingleTag:
1436 case DoubleTag:
1437 case Untagged:
1438 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001439 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301440 }
1441 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001442 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301443}
1444
Gamze Abaka724d0852020-03-18 12:10:24 +00001445func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 var actionCmd openoltpb2.ActionCmd
1447 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001451 if _, ok := actionInfo[VlanPcp]; ok {
1452 action.Cmd.RemarkInnerPbits = true
1453 action.IPbits = actionInfo[VlanPcp].(uint32)
1454 if _, ok := actionInfo[VlanVid]; ok {
1455 action.Cmd.TranslateInnerTag = true
1456 action.IVid = actionInfo[VlanVid].(uint32)
1457 }
1458 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 } else if _, ok := actionInfo[PushVlan]; ok {
1460 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001462 if _, ok := actionInfo[VlanPcp]; ok {
1463 action.OPbits = actionInfo[VlanPcp].(uint32)
1464 action.Cmd.RemarkOuterPbits = true
1465 if _, ok := classifierInfo[VlanVid]; ok {
1466 action.IVid = classifierInfo[VlanVid].(uint32)
1467 action.Cmd.TranslateInnerTag = true
1468 }
1469 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001470 } else if _, ok := actionInfo[TrapToHost]; ok {
1471 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301472 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001473 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301476}
1477
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001478// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1480 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301481}
1482
Gamze Abakafee36392019-10-03 11:17:24 +00001483// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001484func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301485 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001486 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1487
Gamze Abakafee36392019-10-03 11:17:24 +00001488 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301489 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001490 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301491 // return err
1492 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001493 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001494 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001495 }
1496 return nil
1497}
1498
1499// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301500func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001501 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001502 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001503 }
npujarec5762e2020-01-01 14:08:48 +05301504 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301505 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1506 log.Fields{
1507 "tp-id": tpID,
1508 "uni-port-name": uniPortName,
1509 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001510 }
1511 return nil
1512}
1513
David K. Bainbridge794735f2020-02-11 21:01:37 -08001514func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001515
1516 var intfID uint32
1517 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1518 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1519 */
1520 if deviceFlow.AccessIntfId != -1 {
1521 intfID = uint32(deviceFlow.AccessIntfId)
1522 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001523 // We need to log the valid interface ID.
1524 // 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 +00001525 intfID = uint32(deviceFlow.NetworkIntfId)
1526 }
1527
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301529 "flow": *deviceFlow,
1530 "device-id": f.deviceHandler.device.Id,
1531 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001532 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001533
1534 st, _ := status.FromError(err)
1535 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001536 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001537 "err": err,
1538 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301539 "device-id": f.deviceHandler.device.Id,
1540 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001541 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301542 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001543
1544 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301546 log.Fields{"err": err,
1547 "device-flow": deviceFlow,
1548 "device-id": f.deviceHandler.device.Id,
1549 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301553 log.Fields{
1554 "flow": *deviceFlow,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001557
1558 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1559 if deviceFlow.AccessIntfId != -1 {
1560 // No need to register the flow if it is a trap on nni flow.
1561 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1562 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1563 return err
1564 }
1565 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001567}
1568
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1570 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301571 log.Fields{
1572 "flow": *deviceFlow,
1573 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001574 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001575 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001576 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "err": err,
1580 "deviceFlow": deviceFlow,
1581 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001582 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001584 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001585 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001586
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001587 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001589 "of-flow-id": ofFlowID,
1590 "flow": *deviceFlow,
1591 "device-id": f.deviceHandler.device.Id,
1592 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301594}
1595
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001597
1598 classifierInfo := make(map[string]interface{})
1599 actionInfo := make(map[string]interface{})
1600
1601 classifierInfo[EthType] = uint32(LldpEthType)
1602 classifierInfo[PacketTagType] = Untagged
1603 actionInfo[TrapToHost] = true
1604
1605 // LLDP flow is installed to trap LLDP packets on the NNI port.
1606 // We manage flow_id resource pool on per PON port basis.
1607 // Since this situation is tricky, as a hack, we pass the NNI port
1608 // index (network_intf_id) as PON port Index for the flow_id resource
1609 // pool. Also, there is no ONU Id available for trapping LLDP packets
1610 // on NNI port, use onu_id as -1 (invalid)
1611 // ****************** CAVEAT *******************
1612 // This logic works if the NNI Port Id falls within the same valid
1613 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1614 // we need to have a re-look at this.
1615 // *********************************************
1616
1617 var onuID = -1
1618 var uniID = -1
1619 var gemPortID = -1
1620
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301623 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001624 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001625 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001628 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001629
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1631 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301632 return olterrors.NewErrInvalidValue(
1633 log.Fields{
1634 "classifier": classifierInfo,
1635 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001636 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001637 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301638 log.Fields{
1639 "classifier": *classifierProto,
1640 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001641 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301643 return olterrors.NewErrInvalidValue(
1644 log.Fields{
1645 "action": actionInfo,
1646 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "action": *actionProto,
1651 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001652
1653 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1654 OnuId: int32(onuID), // OnuId not required
1655 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001656 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001657 FlowType: Downstream,
1658 NetworkIntfId: int32(networkInterfaceID),
1659 GemportId: int32(gemPortID),
1660 Classifier: classifierProto,
1661 Action: actionProto,
1662 Priority: int32(flow.Priority),
1663 Cookie: flow.Cookie,
1664 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001666 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301667 log.Fields{
1668 "flow": downstreamflow,
1669 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "device-id": f.deviceHandler.device.Id,
1674 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 "flow-id": flow.Id})
1676 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1677 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1678 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301679 log.Fields{
1680 "flow": downstreamflow,
1681 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 }
1683 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301684}
1685
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001686func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1687 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001688}
1689
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001690//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001692 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1693 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1694 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "intf-id": intfID,
1698 "onu-id": onuID,
1699 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001701 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301702 return nil, olterrors.NewErrNotFound("onu-child-device",
1703 log.Fields{
1704 "onu-id": onuID,
1705 "intf-id": intfID,
1706 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001707 }
1708 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1709 //better to ad the device to cache here.
1710 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1711 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301713 log.Fields{
1714 "intf-id": intfID,
1715 "onu-id": onuID,
1716 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001717 }
1718
1719 return onuDev.(*OnuDevice), nil
1720}
1721
1722//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1724 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "pon-port": intfID,
1727 "onu-id": onuID,
1728 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001729 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301732 return nil, olterrors.NewErrNotFound("onu",
1733 log.Fields{
1734 "interface-id": parentPortNo,
1735 "onu-id": onuID,
1736 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001737 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "device-id": f.deviceHandler.device.Id,
1742 "child_device_id": onuDevice.Id,
1743 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301744 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301745}
1746
Neha Sharma96b7bf22020-06-15 10:37:32 +00001747func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1748 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301749 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001750 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301751 log.Fields{
1752 "intf-id": intfID,
1753 "onu-id": onuID,
1754 "uni-id": uniID,
1755 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001756 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301757 }
1758
1759 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "msg": *delGemPortMsg,
1763 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001764 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301765 delGemPortMsg,
1766 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001767 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001768 onuDev.deviceType,
1769 onuDev.deviceID,
1770 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301771 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1772 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001773 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301774 "to-adapter": onuDev.deviceType,
1775 "onu-id": onuDev.deviceID,
1776 "proxyDeviceID": onuDev.proxyDeviceID,
1777 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "msg": delGemPortMsg,
1782 "from-adapter": f.deviceHandler.device.Type,
1783 "to-adapter": onuDev.deviceType,
1784 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301785 return nil
1786}
1787
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1789 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301790 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301792 log.Fields{
1793 "intf-id": intfID,
1794 "onu-id": onuID,
1795 "uni-id": uniID,
1796 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001797 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301798 }
1799
1800 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301802 log.Fields{
1803 "msg": *delTcontMsg,
1804 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001805 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301806 delTcontMsg,
1807 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001808 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001809 onuDev.deviceType,
1810 onuDev.deviceID,
1811 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301812 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1813 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001814 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301815 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1816 "proxyDeviceID": onuDev.proxyDeviceID,
1817 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301818 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001819 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301820 log.Fields{
1821 "msg": delTcontMsg,
1822 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301823 return nil
1824}
1825
Girish Gowdrac3037402020-01-22 20:29:53 +05301826// Once the gemport is released for a given onu, it also has to be cleared from local cache
1827// which was used for deriving the gemport->logicalPortNo during packet-in.
1828// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1829// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001831
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001832 f.onuGemInfoLock.Lock()
1833 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001834
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001837 "gem-port-id": gemPortID,
1838 "intf-id": intfID,
1839 "onu-id": onuID,
1840 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001841 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001842
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001843 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001844deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001845 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301846 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001847 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301848 // If the gemport is found, delete it from local cache.
1849 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001850 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1851 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301853 log.Fields{
1854 "intf-id": intfID,
1855 "onu-id": onuID,
1856 "deletedgemport-id": gemPortID,
1857 "gemports": onu.GemPorts,
1858 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001859 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301860 }
1861 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001862 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301863 }
1864 }
1865}
1866
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301867//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001868// nolint: gocyclo
Girish Gowdraa482f272021-03-24 23:04:19 -07001869func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001870 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001871
Girish Gowdraa482f272021-03-24 23:04:19 -07001872 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1873 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001874 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1875 log.Fields{
1876 "tpPath": tpPath,
1877 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001878 techprofileInst, err := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001879 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1880 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1881 log.Fields{
1882 "tp-id": tpID,
1883 "path": tpPath}, err)
1884 }
1885
1886 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1887
1888 if used {
1889 f.flowsUsedByGemPortKey.Lock()
1890 defer f.flowsUsedByGemPortKey.Unlock()
1891
1892 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1893 for i, flowIDinMap := range flowIDs {
1894 if flowIDinMap == flowID {
1895 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1896 // everytime flowsUsedByGemPort cache is updated the same should be updated
1897 // in kv store by calling UpdateFlowIDsForGem
1898 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
Girish Gowdraa482f272021-03-24 23:04:19 -07001899 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001900 return err
1901 }
1902 break
1903 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001904 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001905 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1906 log.Fields{
1907 "gemport-id": gemPortID,
1908 "usedByFlows": flowIDs,
1909 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001910
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001911 return nil
1912 }
1913 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001914 f.resourceMgr.RemoveGemPortIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1916 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Girish Gowdraa482f272021-03-24 23:04:19 -07001917 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), intfID)
Esin Karamandf392e12020-12-16 13:33:09 +00001918 // also clear gem to uni cache
1919 f.removeFromGemToUniMap(gemPortKey{
Girish Gowdraa482f272021-03-24 23:04:19 -07001920 intfID: intfID,
Esin Karamandf392e12020-12-16 13:33:09 +00001921 gemPort: uint32(gemPortID),
1922 })
Girish Gowdraa482f272021-03-24 23:04:19 -07001923 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001924
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 f.onuIdsLock.Lock() // TODO: What is this lock?
1926
1927 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1928 // by calling DeleteFlowIDsForGem
1929 f.flowsUsedByGemPortKey.Lock()
1930 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1931 f.flowsUsedByGemPortKey.Unlock()
Girish Gowdraa482f272021-03-24 23:04:19 -07001932 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1933 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934
1935 f.onuIdsLock.Unlock()
1936
1937 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001938 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1940 log.Fields{
1941 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001942 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943 "onu-id": onuID,
1944 "uni-id": uniID,
1945 "device-id": f.deviceHandler.device.Id,
1946 "gemport-id": gemPortID})
1947 }
1948 switch techprofileInst := techprofileInst.(type) {
1949 case *tp.TechProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001950 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001951 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001952 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953 logger.Warn(ctx, err)
1954 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001955 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001956 logger.Warn(ctx, err)
1957 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001958 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001959 logger.Warn(ctx, err)
1960 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001961 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 logger.Warn(ctx, err)
1963 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001964 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001965 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001966 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001967 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1968 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001969 "intf": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001970 "onu-id": onuID,
1971 "uni-id": uniID,
1972 "device-id": f.deviceHandler.device.Id,
1973 "alloc-id": techprofileInst.UsScheduler.AllocID})
1974 }
1975 }
1976 case *tp.EponProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001977 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 logger.Warn(ctx, err)
1979 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001980 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 logger.Warn(ctx, err)
1982 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001983 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001985 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301987 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001988 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301989 "onu-id": onuID,
1990 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001991 "device-id": f.deviceHandler.device.Id,
1992 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001993 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001994 default:
1995 logger.Errorw(ctx, "error-unknown-tech",
1996 log.Fields{
1997 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001998 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001999
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302000 return nil
2001}
2002
David K. Bainbridge794735f2020-02-11 21:01:37 -08002003// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002004func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002005 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302007 log.Fields{
2008 "flowDirection": flowDirection,
2009 "flow": *flow,
2010 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002011
2012 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002013 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002014 }
2015
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302016 classifierInfo := make(map[string]interface{})
2017
Neha Sharma96b7bf22020-06-15 10:37:32 +00002018 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002020 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002021 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302022 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302023
David K. Bainbridge794735f2020-02-11 21:01:37 -08002024 onuID := int32(onu)
2025 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302026
2027 for _, field := range flows.GetOfbFields(flow) {
2028 if field.Type == flows.IP_PROTO {
2029 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002030 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302031 }
2032 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002033 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302034 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002035 "flow-id": flow.Id,
2036 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302037 "onu-id": onuID,
2038 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039
2040 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2041 onuID = -1
2042 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2044 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002045 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 log.Fields{
2048 "port-number": inPort,
2049 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002050 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002051 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002053 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2054 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})
2055 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2056 }
2057 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2058 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2059 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2060 return err
2061 }
2062 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2063 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2064 return err
2065 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002066 tpID, err := getTpIDFromFlow(ctx, flow)
2067 if err != nil {
2068 return olterrors.NewErrNotFound("tp-id",
2069 log.Fields{
2070 "flow": flow,
2071 "intf-id": Intf,
2072 "onu-id": onuID,
2073 "uni-id": uniID,
2074 "device-id": f.deviceHandler.device.Id}, err)
2075 }
2076
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002077 if !flowInfo.Flow.ReplicateFlow {
Girish Gowdra82c80982021-03-26 16:22:02 -07002078 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002079 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002080 "flow-id": flow.Id,
2081 "stored-flow": flowInfo.Flow,
2082 "device-id": f.deviceHandler.device.Id,
2083 "stored-flow-id": flowInfo.Flow.FlowId,
2084 "onu-id": onuID,
2085 "intf": Intf,
Girish Gowdra82c80982021-03-26 16:22:02 -07002086 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002087 })
2088 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302089 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002090 } else {
2091 gems := make([]uint32, 0)
2092 for _, gem := range flowInfo.Flow.PbitToGemport {
2093 gems = appendUnique32bit(gems, gem)
2094 }
2095 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2096 for _, gem := range gems {
Girish Gowdra82c80982021-03-26 16:22:02 -07002097 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002098 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002099 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002101 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002102 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002103 "onu-id": onuID,
2104 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 "gem": gem,
Girish Gowdra82c80982021-03-26 16:22:02 -07002106 "err": err,
Matteo Scandolo92186242020-06-12 10:54:18 -07002107 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002108 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302109 }
2110 }
2111 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002112
2113 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2114 if isDatapathFlow(flow) {
2115 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2116 var inverseDirection string
2117 if flowDirection == Upstream {
2118 inverseDirection = Downstream
2119 } else {
2120 inverseDirection = Upstream
2121 }
2122
2123 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002124 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002125 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002126 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002127 }
2128 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002129 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2130 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2131 return err
2132 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002133 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002134}
2135
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002136//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002137func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002138
Matteo Scandolo66fbaf52021-03-24 14:13:38 -07002139 logger.Infow(ctx, "removing-flow", log.Fields{
2140 "flow": *flow,
2141 "device-id": f.deviceHandler.device.Id,
2142 })
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302143 var direction string
2144 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002145
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302146 for _, action := range flows.GetActions(flow) {
2147 if action.Type == flows.OUTPUT {
2148 if out := action.GetOutput(); out != nil {
2149 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002150 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302151 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002152 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002153 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002154 }
2155 }
2156 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002157
2158 if flows.HasGroup(flow) {
2159 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002160 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002161 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302162 direction = Upstream
2163 } else {
2164 direction = Downstream
2165 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302166
Girish Gowdracefae192020-03-19 18:14:10 -07002167 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002168 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002169
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002170 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002171}
2172
Esin Karamanae41e2b2019-12-17 18:13:13 +00002173//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2174func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2175 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2176 if ethType, ok := classifierInfo[EthType]; ok {
2177 if ethType.(uint32) == IPv4EthType {
2178 if ipProto, ok := classifierInfo[IPProto]; ok {
2179 if ipProto.(uint32) == IgmpProto {
2180 return true
2181 }
2182 }
2183 }
2184 }
2185 }
2186 return false
2187}
2188
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002189// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2190func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2191 // Step1 : Fill flowControlBlock
2192 // Step2 : Push the flowControlBlock to ONU channel
2193 // Step3 : Wait on response channel for response
2194 // Step4 : Return error value
2195 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2196 errChan := make(chan error)
2197 flowCb := flowControlBlock{
2198 ctx: ctx,
2199 addFlow: addFlow,
2200 flow: flow,
2201 flowMetadata: flowMetadata,
2202 errChan: &errChan,
2203 }
2204 inPort, outPort := getPorts(flow)
2205 var onuID uint32
2206 if inPort != InvalidPort && outPort != InvalidPort {
2207 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2208 }
2209 // inPort or outPort is InvalidPort for trap-from-nni flows.
2210 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2211 // Send the flowCb on the ONU flow channel
2212 f.incomingFlows[onuID] <- flowCb
2213 // Wait on the channel for flow handlers return value
2214 err := <-errChan
2215 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2216 return err
2217}
2218
2219// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2220// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2221func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2222 for {
2223 // block on the channel to receive an incoming flow
2224 // process the flow completely before proceeding to handle the next flow
2225 flowCb := <-subscriberFlowChannel
2226 if flowCb.addFlow {
2227 logger.Debugw(flowCb.ctx, "adding-flow",
2228 log.Fields{"device-id": f.deviceHandler.device.Id,
2229 "flowToAdd": flowCb.flow})
2230 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2231 // Pass the return value over the return channel
2232 *flowCb.errChan <- err
2233 } else {
2234 logger.Debugw(flowCb.ctx, "removing-flow",
2235 log.Fields{"device-id": f.deviceHandler.device.Id,
2236 "flowToRemove": flowCb.flow})
2237 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2238 // Pass the return value over the return channel
2239 *flowCb.errChan <- err
2240 }
2241 }
2242}
2243
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002244// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302245// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002246func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002247 classifierInfo := make(map[string]interface{})
2248 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002249 var UsMeterID uint32
2250 var DsMeterID uint32
2251
Neha Sharma96b7bf22020-06-15 10:37:32 +00002252 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302253 log.Fields{
2254 "flow": flow,
Matteo Scandolo66fbaf52021-03-24 14:13:38 -07002255 "flowmetadata": flowMetadata,
2256 "device-id": f.deviceHandler.device.Id,
2257 })
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002259
Neha Sharma96b7bf22020-06-15 10:37:32 +00002260 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002261 if err != nil {
2262 // Error logging is already done in the called function
2263 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002264 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302265 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002266
Esin Karamanccb714b2019-11-29 15:02:06 +00002267 if flows.HasGroup(flow) {
2268 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002269 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002270 }
2271
manikkaraj k17652a72019-05-06 09:06:36 -04002272 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002273 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002274 if err != nil {
2275 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002276 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002277 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002278
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302280 log.Fields{
2281 "classifierinfo_inport": classifierInfo[InPort],
2282 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002283 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002284
Humera Kouser94d7a842019-08-25 19:04:32 -04002285 if ethType, ok := classifierInfo[EthType]; ok {
2286 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002287 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002288 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002289 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002290 if ethType.(uint32) == PPPoEDEthType {
2291 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2292 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2293 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2294 }
2295 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002296 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002297 if ipProto, ok := classifierInfo[IPProto]; ok {
2298 if ipProto.(uint32) == IPProtoDhcp {
2299 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302300 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002302 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002303 }
2304 }
2305 }
2306 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002307 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002308 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002309 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002310 }
A R Karthick1f85b802019-10-11 05:06:05 +00002311
npujarec5762e2020-01-01 14:08:48 +05302312 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002313
Neha Sharma96b7bf22020-06-15 10:37:32 +00002314 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002315 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302316 return olterrors.NewErrNotFound("tpid-for-flow",
2317 log.Fields{
2318 "flow": flow,
2319 "intf-id": IntfID,
2320 "onu-id": onuID,
2321 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002322 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302324 log.Fields{
2325 "tp-id": TpID,
2326 "intf-id": intfID,
2327 "onu-id": onuID,
2328 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002329 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002330 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002332 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002333 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002334 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002335
2336 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002337 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002338}
Girish Gowdra3d633032019-12-10 16:37:05 +05302339
Esin Karamanccb714b2019-11-29 15:02:06 +00002340// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002341func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002342 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002343 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302344 "classifier-info": classifierInfo,
2345 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002346
Esin Karaman65409d82020-03-18 10:58:18 +00002347 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002348 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002349 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002350 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002351
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002352 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002353
David K. Bainbridge794735f2020-02-11 21:01:37 -08002354 onuID := NoneOnuID
2355 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002356
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002357 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002359 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002360 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002361 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2362 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002363 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
2365 groupID := actionInfo[GroupID].(uint32)
2366 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002367 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002368 FlowType: Multicast,
2369 NetworkIntfId: int32(networkInterfaceID),
2370 GroupId: groupID,
2371 Classifier: classifierProto,
2372 Priority: int32(flow.Priority),
2373 Cookie: flow.Cookie}
2374
Kent Hagermane6ff1012020-07-14 15:07:53 -04002375 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002376 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002377 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002379 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002380 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002381 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002382 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002383 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002384 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002385 //cached group can be removed now
2386 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2387 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2388 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002389 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002390
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002391 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2392 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2393 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002394 }
2395 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002396}
2397
Esin Karaman65409d82020-03-18 10:58:18 +00002398//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2399func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2400 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002402 if err != nil {
2403 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2404 }
2405 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002406 }
Esin Karaman65409d82020-03-18 10:58:18 +00002407 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302408 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002409 if e == nil && len(nniPorts) > 0 {
2410 return nniPorts[0], nil
2411 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302412 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002413}
2414
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002415//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002417
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302419 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002420 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302421 log.Fields{
2422 "intf-id": intfID,
2423 "onu-id": onuID,
2424 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002425 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302426 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002428
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002430 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002431 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002432 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002433 tpDownloadMsg,
2434 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002435 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002436 onuDev.deviceType,
2437 onuDev.deviceID,
2438 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002439 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302440 return olterrors.NewErrCommunication("send-techprofile-download-request",
2441 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002442 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302443 "to-adapter": onuDev.deviceType,
2444 "onu-id": onuDev.deviceID,
2445 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002446 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002447 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302448 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302449}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002450
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302451//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002452func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302453
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002454 f.onuGemInfoLock.Lock()
2455 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002456 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002457 // If the ONU already exists in onuGemInfo list, nothing to do
2458 for _, onu := range onugem {
2459 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2460 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2461 log.Fields{"onuID": onuID,
2462 "serialNum": serialNum})
2463 return nil
2464 }
2465 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002466
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302467 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002468 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002469 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002470 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302471 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002472 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302473 log.Fields{
2474 "intf-id": intfID,
2475 "onu-id": onuID,
2476 "serial-num": serialNum,
2477 "onu": onu,
2478 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002479 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002480}
2481
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302482//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302483func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002484
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002485 f.onuGemInfoLock.Lock()
2486 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002487
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302489 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002490 "gem-port-id": gemPort,
2491 "intf-id": intfID,
2492 "onu-id": onuID,
2493 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002494 "onu-gem": f.onuGemInfo})
2495 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302496 // update the gem to the local cache as well as to kv strore
2497 for idx, onu := range onugem {
2498 if onu.OnuID == onuID {
2499 // check if gem already exists , else update the cache and kvstore
2500 for _, gem := range onu.GemPorts {
2501 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302503 log.Fields{
2504 "gem": gemPort,
2505 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302506 return
2507 }
2508 }
2509 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002510 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002511 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302512 }
2513 }
npujarec5762e2020-01-01 14:08:48 +05302514 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302515 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302517 log.Fields{
2518 "intf-id": intfID,
2519 "onu-id": onuID,
2520 "gemPort": gemPort,
2521 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002522 return
2523 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002524 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302525 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002526 "gem-port-id": gemPort,
2527 "intf-id": intfID,
2528 "onu-id": onuID,
2529 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002530 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002531}
2532
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002533//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302534func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002535 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002536 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002537 var err error
2538
2539 if packetIn.IntfType == "pon" {
2540 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002541 // get onu and uni ids associated with the given pon and gem ports
2542 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002543 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544 return logicalPortNum, err
2545 }
Esin Karamandf392e12020-12-16 13:33:09 +00002546 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2547
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 if packetIn.PortNo != 0 {
2549 logicalPortNum = packetIn.PortNo
2550 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002551 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 }
2553 // 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 +00002554 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002555 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002556 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002557 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002558
2559 if logger.V(log.DebugLevel) {
2560 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2561 log.Fields{
2562 "logical-port-num": logicalPortNum,
2563 "intf-type": packetIn.IntfType,
2564 "packet": hex.EncodeToString(packetIn.Pkt),
2565 })
2566 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002567 return logicalPortNum, nil
2568}
2569
Esin Karamandf392e12020-12-16 13:33:09 +00002570//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2571func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2572 key := gemPortKey{
2573 intfID: intfID,
2574 gemPort: gemPortID,
2575 }
2576 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2577 if ok {
2578 if len(uniPortInfo) > 1 {
2579 //return onu ID and uni port from the cache
2580 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2581 log.Fields{
2582 "intfID": intfID,
2583 "gemPortID": gemPortID,
2584 "onuID, uniID": uniPortInfo})
2585 return uniPortInfo[0], uniPortInfo[1], nil
2586 }
2587 }
2588 //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.
2589 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2590 if err == nil {
2591 f.toGemToUniMap(ctx, key, onuID, uniID)
2592 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2593 log.Fields{
2594 "gemPortKey": key,
2595 "onuID": onuID,
2596 "uniID": uniID})
2597 return onuID, uniID, nil
2598 }
2599 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2600 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2601 errors.New("no uni port found"))
2602}
2603
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002604//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002605func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002606 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002607
2608 ctag, priority, err := getCTagFromPacket(ctx, packet)
2609 if err != nil {
2610 return 0, err
2611 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302612
Esin Karaman7fb80c22020-07-16 14:23:33 +00002613 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002614 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002615 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002616 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002617 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302618 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002619 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302620 log.Fields{
2621 "pktinkey": pktInkey,
2622 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002623
2624 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002625 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626 //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 +00002627 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302628 if err == nil {
2629 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002630 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302631 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002632 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002633 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302634 log.Fields{
2635 "pktinkey": pktInkey,
2636 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 return gemPortID, nil
2638 }
2639 }
Shrey Baid26912972020-04-16 21:02:31 +05302640 return uint32(0), olterrors.NewErrNotFound("gem-port",
2641 log.Fields{
2642 "pktinkey": pktInkey,
2643 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002644
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002645}
2646
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002647func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2648 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002650 classifier[PacketTagType] = DoubleTag
2651 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002652 /* We manage flowId resource pool on per PON port basis.
2653 Since this situation is tricky, as a hack, we pass the NNI port
2654 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002655 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656 on NNI port, use onu_id as -1 (invalid)
2657 ****************** CAVEAT *******************
2658 This logic works if the NNI Port Id falls within the same valid
2659 range of PON Port Ids. If this doesn't work for some OLT Vendor
2660 we need to have a re-look at this.
2661 *********************************************
2662 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002663 onuID := -1
2664 uniID := -1
2665 gemPortID := -1
2666 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302668 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302669 return olterrors.NewErrNotFound("nni-intreface-id",
2670 log.Fields{
2671 "classifier": classifier,
2672 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002673 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302674 }
2675
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002676 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002677 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002678 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002679 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002681 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2682 log.Fields{
2683 "classifier": classifier,
2684 "action": action,
2685 "flowId": logicalFlow.Id,
2686 "intf-id": networkInterfaceID})
2687
David K. Bainbridge794735f2020-02-11 21:01:37 -08002688 classifierProto, err := makeOpenOltClassifierField(classifier)
2689 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002690 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002691 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002692 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002693 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002694 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002695 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002696 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002697 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002698 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2699 OnuId: int32(onuID), // OnuId not required
2700 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002701 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002702 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002703 AllocId: int32(allocID), // AllocId not used
2704 NetworkIntfId: int32(networkInterfaceID),
2705 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002706 Classifier: classifierProto,
2707 Action: actionProto,
2708 Priority: int32(logicalFlow.Priority),
2709 Cookie: logicalFlow.Cookie,
2710 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002711 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002712 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002713 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002714 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002715 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2716 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2717 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002718 }
2719 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002720}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002721
Esin Karamanae41e2b2019-12-17 18:13:13 +00002722//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2723func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2724 var packetType string
2725 ovid, ivid := false, false
2726 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2727 vid := vlanID & VlanvIDMask
2728 if vid != ReservedVlan {
2729 ovid = true
2730 }
2731 }
2732 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2733 vid := uint32(metadata)
2734 if vid != ReservedVlan {
2735 ivid = true
2736 }
2737 }
2738 if ovid && ivid {
2739 packetType = DoubleTag
2740 } else if !ovid && !ivid {
2741 packetType = Untagged
2742 } else {
2743 packetType = SingleTag
2744 }
2745 return packetType
2746}
2747
2748//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002749func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002750 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002751 action := make(map[string]interface{})
2752 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2753 action[TrapToHost] = true
2754 /* We manage flowId resource pool on per PON port basis.
2755 Since this situation is tricky, as a hack, we pass the NNI port
2756 index (network_intf_id) as PON port Index for the flowId resource
2757 pool. Also, there is no ONU Id available for trapping packets
2758 on NNI port, use onu_id as -1 (invalid)
2759 ****************** CAVEAT *******************
2760 This logic works if the NNI Port Id falls within the same valid
2761 range of PON Port Ids. If this doesn't work for some OLT Vendor
2762 we need to have a re-look at this.
2763 *********************************************
2764 */
2765 onuID := -1
2766 uniID := -1
2767 gemPortID := -1
2768 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002769 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002770 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302771 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002772 "classifier": classifier,
2773 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002774 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002775 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002777 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002778 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002780
David K. Bainbridge794735f2020-02-11 21:01:37 -08002781 classifierProto, err := makeOpenOltClassifierField(classifier)
2782 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002783 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002786 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002787 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002788 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002789 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002790 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002791 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2792 OnuId: int32(onuID), // OnuId not required
2793 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002794 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002795 FlowType: Downstream,
2796 AllocId: int32(allocID), // AllocId not used
2797 NetworkIntfId: int32(networkInterfaceID),
2798 GemportId: int32(gemPortID), // GemportId not used
2799 Classifier: classifierProto,
2800 Action: actionProto,
2801 Priority: int32(logicalFlow.Priority),
2802 Cookie: logicalFlow.Cookie,
2803 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002804 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002805 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002807 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002808 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2809 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2810 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002811 }
2812 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002813}
2814
salmansiddiqui7ac62132019-08-22 03:58:50 +00002815func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2816 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302817 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002818 }
2819 if Dir == tp_pb.Direction_UPSTREAM {
2820 return "upstream", nil
2821 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2822 return "downstream", nil
2823 }
2824 return "", nil
2825}
2826
Kent Hagermane6ff1012020-07-14 15:07:53 -04002827// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302828func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002829 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002830 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002831 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002832 intfID := args[IntfID]
2833 onuID := args[OnuID]
2834 uniID := args[UniID]
2835 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002836 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002837 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002838 gemToAes := make(map[uint32]bool)
2839
2840 var attributes []tp.IGemPortAttribute
2841 var direction = tp_pb.Direction_UPSTREAM
2842 switch TpInst := TpInst.(type) {
2843 case *tp.TechProfile:
2844 if IsUpstream(actionInfo[Output].(uint32)) {
2845 attributes = TpInst.UpstreamGemPortAttributeList
2846 } else {
2847 attributes = TpInst.DownstreamGemPortAttributeList
2848 direction = tp_pb.Direction_DOWNSTREAM
2849 }
2850 default:
2851 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2852 return
2853 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002854
2855 if len(gemPorts) == 1 {
2856 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002857 gemPortID = gemPorts[0]
2858 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002859 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2860 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002861 pBitMap := attributes[idx].PbitMap
2862 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2863 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2864 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2865 // this pcp bit traffic.
2866 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2867 if pbitSet == pbit1 {
2868 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2869 pbitToGem[pcp] = gemID
2870 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002871 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002872 }
2873 }
2874 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2876 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2877 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2878 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002879 }
2880
Gamze Abaka7650be62021-02-26 10:50:36 +00002881 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2882 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2883
salmansiddiqui7ac62132019-08-22 03:58:50 +00002884 if ipProto, ok := classifierInfo[IPProto]; ok {
2885 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002886 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002887 "tp-id": tpID,
2888 "alloc-id": allocID,
2889 "intf-id": intfID,
2890 "onu-id": onuID,
2891 "uni-id": uniID,
2892 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002893 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002894 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002895 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002896 }
2897
Girish Gowdra32625212020-04-29 11:26:35 -07002898 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302900 log.Fields{
2901 "intf-id": intfID,
2902 "onu-id": onuID,
2903 "uni-id": uniID,
2904 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002905 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002906 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002907 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 return
2911 }
2912 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002913 if ethType.(uint32) == EapEthType {
2914 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002915 "intf-id": intfID,
2916 "onu-id": onuID,
2917 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002918 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002919 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 var vlanID uint32
2921 if val, ok := classifierInfo[VlanVid]; ok {
2922 vlanID = (val.(uint32)) & VlanvIDMask
2923 } else {
2924 vlanID = DefaultMgmtVlan
2925 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002926 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002927 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002929 } else if ethType.(uint32) == PPPoEDEthType {
2930 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2931 "tp-id": tpID,
2932 "alloc-id": allocID,
2933 "intf-id": intfID,
2934 "onu-id": onuID,
2935 "uni-id": uniID,
2936 })
2937 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002938 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002939 logger.Warn(ctx, err)
2940 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002942 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002944 "intf-id": intfID,
2945 "onu-id": onuID,
2946 "uni-id": uniID,
2947 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002948 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002950 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002953 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002954 "intf-id": intfID,
2955 "onu-id": onuID,
2956 "uni-id": uniID,
2957 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002958 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002959 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002960 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 }
2962 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302964 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002965 "intf-id": intfID,
2966 "onu-id": onuID,
2967 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302968 "classifier": classifierInfo,
2969 "action": actionInfo,
2970 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 return
2972 }
2973 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002974 go func() {
2975 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2976 logger.Warn(ctx, err)
2977 }
2978 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002979}
2980
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002981func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2982 f.flowsUsedByGemPortKey.RLock()
2983 flowIDList := f.flowsUsedByGemPort[gemPortID]
2984 f.flowsUsedByGemPortKey.RUnlock()
2985 return len(flowIDList) > 1
2986
Gamze Abakafee36392019-10-03 11:17:24 +00002987}
2988
npujarec5762e2020-01-01 14:08:48 +05302989func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2990 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002991 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2992 for _, currentGemPort := range currentGemPorts {
2993 for _, tpGemPort := range tpGemPorts {
2994 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2995 return true, currentGemPort
2996 }
2997 }
2998 }
Girish Gowdra54934262019-11-13 14:19:55 +05302999 if tpInst.InstanceCtrl.Onu == "single-instance" {
3000 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003001 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003002 logger.Warn(ctx, err)
3003 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003004 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003005 logger.Warn(ctx, err)
3006 }
Girish Gowdra54934262019-11-13 14:19:55 +05303007
3008 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3009 // still be used on other uni ports.
3010 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3011 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003012 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303014 for i := 0; i < len(tpInstances); i++ {
3015 tpI := tpInstances[i]
3016 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303017 for _, tpGemPort := range tpGemPorts {
3018 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303020 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303021 }
3022 }
3023 }
3024 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003026 return false, 0
3027}
3028
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003030 for _, field := range flows.GetOfbFields(flow) {
3031 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003034 } else if field.Type == flows.ETH_DST {
3035 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003037 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003040 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003043 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303044 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003046 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003049 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003051 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003052 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003055 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003057 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003058 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003059 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003061 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003062 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003064 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003066 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 return
3070 }
3071 }
3072}
3073
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003075 for _, action := range flows.GetActions(flow) {
3076 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003078 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003081 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 }
Scott Baker355d1742019-10-24 10:57:52 -07003083 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003086 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 if out := action.GetPush(); out != nil {
3088 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 } else {
3091 actionInfo[PushVlan] = true
3092 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303094 log.Fields{
3095 "push-tpid": actionInfo[TPID].(uint32),
3096 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 }
3098 }
Scott Baker355d1742019-10-24 10:57:52 -07003099 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003100 if out := action.GetSetField(); out != nil {
3101 if field := out.GetField(); field != nil {
3102 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003103 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3106 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003107 }
3108 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003109 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003110 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003112 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003113 }
3114 }
3115 return nil
3116}
3117
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003119 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003120 fieldtype := ofbField.GetType()
3121 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003122 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3123 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003125 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003128 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3129 pcp := ofbField.GetVlanPcp()
3130 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003131 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003132 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 }
3135 }
3136}
3137
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003141 } else {
3142 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003143 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003144 }
3145}
3146
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003148 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003150 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3151 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003152 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003153 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303155 log.Fields{
3156 "newinport": classifierInfo[InPort].(uint32),
3157 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303159 return olterrors.NewErrNotFound("child-in-port",
3160 log.Fields{
3161 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3162 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 }
3164 }
3165 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003166 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003167 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003168 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003169 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003170 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303172 log.Fields{
3173 "newoutport": actionInfo[Output].(uint32),
3174 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303176 return olterrors.NewErrNotFound("out-port",
3177 log.Fields{
3178 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3179 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003180 }
3181 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3182 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003183 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003184 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303186 log.Fields{
3187 "newinport": 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("nni-port",
3191 log.Fields{
3192 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3193 "in-port": classifierInfo[InPort].(uint32),
3194 "out-port": actionInfo[Output].(uint32),
3195 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003196 }
3197 }
3198 }
3199 return nil
3200}
Gamze Abakafee36392019-10-03 11:17:24 +00003201
Neha Sharma96b7bf22020-06-15 10:37:32 +00003202func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003203 /* Metadata 8 bytes:
3204 Most Significant 2 Bytes = Inner VLAN
3205 Next 2 Bytes = Tech Profile ID(TPID)
3206 Least Significant 4 Bytes = Port ID
3207 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3208 subscriber related flows.
3209 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003211 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003212 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003213 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003215 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003216}
3217
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003218func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3219 for _, sliceElement := range slice {
3220 if sliceElement == item {
3221 return slice
3222 }
3223 }
3224 return append(slice, item)
3225}
3226
3227func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003228 for _, sliceElement := range slice {
3229 if sliceElement == item {
3230 return slice
3231 }
3232 }
3233 return append(slice, item)
3234}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303235
3236// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003237func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303238
3239 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3240 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003241 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003242 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003243 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003244 log.Fields{
3245 "port-number": action[Output].(uint32),
3246 "error": err})
3247 return uint32(0), err
3248 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303250 return intfID, nil
3251 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003252 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003253 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003254 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003255 log.Fields{
3256 "port-number": action[Output].(uint32),
3257 "error": err})
3258 return uint32(0), err
3259 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303261 return intfID, nil
3262 }
3263 return uint32(0), nil
3264}
3265
3266// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003267func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3268 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3269 if err != nil {
3270 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3271 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3272 return
3273 }
3274 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003275
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003276 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003277 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003278 f.packetInGemPortLock.RUnlock()
3279
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303280 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003281 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282 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 +05303283 log.Fields{
3284 "pktinkey": pktInkey,
3285 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003286 return
3287 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303288 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003289 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003290 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003291 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003292
npujarec5762e2020-01-01 14:08:48 +05303293 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003294 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 +05303295 log.Fields{
3296 "pktinkey": pktInkey,
3297 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303298}
3299
Esin Karaman7fb80c22020-07-16 14:23:33 +00003300//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3301func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3302 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003303 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003304 return 0, 0, errors.New("invalid packet length")
3305 }
3306 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3307 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3308
3309 var index int8
3310 if outerEthType == 0x8100 {
3311 if innerEthType == 0x8100 {
3312 // q-in-q 802.1ad or 802.1q double tagged packet.
3313 // get the inner vlanId
3314 index = 18
3315 } else {
3316 index = 14
3317 }
3318 priority := (packet[index] >> 5) & 0x7
3319 //13 bits composes vlanId value
3320 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3321 return vlan, priority, nil
3322 }
3323 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3324 return 0, 0, nil
3325}
3326
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303327// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303328func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003329
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003330 f.onuGemInfoLock.Lock()
3331 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003332
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003333 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303334 for idx, onu := range onugem {
3335 if onu.OnuID == onuID {
3336 for _, uni := range onu.UniPorts {
3337 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003338 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 +05303339 return
3340 }
3341 }
3342 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003343 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303344 }
3345 }
npujarec5762e2020-01-01 14:08:48 +05303346 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003347
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303348}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303349
npujarec5762e2020-01-01 14:08:48 +05303350func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3351 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303352 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003353 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303354 return
3355 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003356 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303357 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003358 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303359 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003360 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303361}
Esin Karamanccb714b2019-11-29 15:02:06 +00003362
Girish Gowdra9602eb42020-09-09 15:50:39 -07003363//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3364// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003365func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003366 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003368 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3369 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3370
Esin Karamanccb714b2019-11-29 15:02:06 +00003371 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003372 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 -07003373 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003374 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003375
3376 var onuID = int32(NoneOnuID)
3377 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003378 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3379 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3380 log.Fields{
3381 "flow": flow,
3382 "device-id": f.deviceHandler.device.Id,
3383 "intf-id": networkInterfaceID,
3384 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003385 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003386 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3387 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3388 log.Fields{
3389 "flow": flowInfo.Flow,
3390 "flow-id": flow.Id,
3391 "device-id": f.deviceHandler.device.Id})
3392 // Remove from device
3393 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3394 // DKB
3395 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3396 log.Fields{
3397 "flow-id": flow.Id,
3398 "error": err})
3399 return err
3400 }
3401 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003402 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003403}
3404
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003405// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3406func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3407 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3408 if err != nil {
3409 _ = olterrors.NewErrNotFound("onu", log.Fields{
3410 "pon-port": f.ponPortIdx}, err).Log()
3411 return
3412 }
3413
3414 f.subscriberDataPathFlowIDMapLock.Lock()
3415 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3416
3417 for _, onu := range onuGemInfo {
3418 for _, uniID := range onu.UniPorts {
3419 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3420 if err != nil {
3421 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3422 }
3423 for _, flowID := range flowIDs {
3424 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3425 if flowInfo == nil {
3426 // Error is already logged in the called function
3427 continue
3428 }
3429 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3430 flowInfo.Flow.FlowType == Downstream &&
3431 flowInfo.Flow.Classifier.OVid > 0 &&
3432 flowInfo.Flow.TechProfileId > 0 {
3433 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3434 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3435 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3436 }
3437 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3438 flowInfo.Flow.FlowType == Upstream &&
3439 flowInfo.Flow.Action.OVid > 0 &&
3440 flowInfo.Flow.TechProfileId > 0 {
3441 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3442 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3443 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3444 }
3445 }
3446 }
3447 }
3448 }
3449}
3450
3451// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3452func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3453 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3454}