blob: 4ae86acb24dcbf7d61ce54e65f4c7b0531fe254f [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
Gamze Abakacb0e6772021-06-10 08:32:12 +0000561 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
562 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
563 log.Fields{
564 "direction": sq.direction,
565 "TrafficScheds": TrafficSched,
566 "device-id": f.deviceHandler.device.Id,
567 "intfID": sq.intfID,
568 "onuID": sq.onuID,
569 "uniID": sq.uniID})
570 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
571 IntfId: sq.intfID, OnuId: sq.onuID,
572 UniId: sq.uniID, PortNo: sq.uniPort,
573 TrafficScheds: TrafficSched}); err != nil {
574 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
575 }
576 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
577 "direction": sq.direction,
578 "traffic-queues": trafficQueues,
579 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000580 }
581
582 // On receiving the CreateTrafficQueues request, the driver should create corresponding
583 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530585 log.Fields{"direction": sq.direction,
586 "traffic-queues": trafficQueues,
587 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530588 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
590 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000591 TrafficQueues: trafficQueues,
592 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530593 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530596 "direction": sq.direction,
597 "traffic-queues": trafficQueues,
598 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599
Esin Karamanccb714b2019-11-29 15:02:06 +0000600 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000601 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000602 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700603 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000604 //assumed that there is only one queue per PON for the multicast service
605 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
606 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000607 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000608 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700609 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000610 gemPortID: multicastQueuePerPonPort.GemportId,
611 servicePriority: multicastQueuePerPonPort.Priority,
612 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700613 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000614 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400615 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
616 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
617 return err
618 }
Shrey Baid26912972020-04-16 21:02:31 +0530619
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000621 }
622 }
623 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000624 return nil
625}
626
salmansiddiqui7ac62132019-08-22 03:58:50 +0000627// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530628func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400629
630 var Direction string
631 var SchedCfg *tp_pb.SchedulerConfig
632 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000633 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530634 log.Fields{
635 "direction": sq.direction,
636 "intf-id": sq.intfID,
637 "onu-id": sq.onuID,
638 "uni-id": sq.uniID,
639 "uni-port": sq.uniPort,
640 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000641 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000642 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400643 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000644 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000645 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400646 Direction = "downstream"
647 }
648
Girish Kumar8f73fe02019-12-09 13:19:37 +0000649 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530650 return olterrors.NewErrNotFound("scheduler-config",
651 log.Fields{
652 "int-id": sq.intfID,
653 "direction": sq.direction,
654 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000655 }
656
Girish Gowdraa482f272021-03-24 23:04:19 -0700657 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 -0400658
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700659 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000660 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000661
Neha Sharma96b7bf22020-06-15 10:37:32 +0000662 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000663 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530664 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
665 log.Fields{
666 "intf-id": sq.intfID,
667 "direction": sq.direction,
668 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000669 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670
npujarec5762e2020-01-01 14:08:48 +0530671 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000672 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
673 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000674 TrafficQueues: TrafficQueues,
675 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000676 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530677 log.Fields{
678 "intf-id": sq.intfID,
679 "traffic-queues": TrafficQueues,
680 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 }
Gamze Abakacb0e6772021-06-10 08:32:12 +0000682 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400683
Gamze Abakacb0e6772021-06-10 08:32:12 +0000684 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
685 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
686 IntfId: sq.intfID, OnuId: sq.onuID,
687 UniId: sq.uniID, PortNo: sq.uniPort,
688 TrafficScheds: TrafficSched}); err != nil {
689 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
690 log.Fields{
691 "intf-id": sq.intfID,
692 "traffic-schedulers": TrafficSched,
693 "onu-id": sq.onuID,
694 "uni-id": sq.uniID,
695 "uni-port": sq.uniPort}, err)
696 }
697
698 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
699 log.Fields{"device-id": f.deviceHandler.device.Id,
700 "intf-id": sq.intfID,
701 "onu-id": sq.onuID,
702 "uni-id": sq.uniID,
703 "uni-port": sq.uniPort})
704
705 if sq.direction == tp_pb.Direction_UPSTREAM {
706 allocID := sq.tpInst.(*tp.TechProfile).UsScheduler.AllocID
707 f.resourceMgr.FreeAllocID(ctx, sq.intfID, sq.onuID, sq.uniID, allocID)
708 // Delete the TCONT on the ONU.
709 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
710 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
711 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
712 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
713 log.Fields{
714 "intf": sq.intfID,
715 "onu-id": sq.onuID,
716 "uni-id": sq.uniID,
717 "device-id": f.deviceHandler.device.Id,
718 "alloc-id": allocID})
719 }
720 }
721 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000722
723 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400724 * delete the meter id on the KV store.
725 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700726 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400727 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530728 return olterrors.NewErrAdapter("unable-to-remove-meter",
729 log.Fields{
730 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700731 "device-id": f.deviceHandler.device.Id,
732 "intf-id": sq.intfID,
733 "onu-id": sq.onuID,
734 "uni-id": sq.uniID,
735 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000737 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530738 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530739 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700740 "device-id": f.deviceHandler.device.Id,
741 "intf-id": sq.intfID,
742 "onu-id": sq.onuID,
743 "uni-id": sq.uniID,
744 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400745 return err
746}
747
Gamze Abakafee36392019-10-03 11:17:24 +0000748// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700749func (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 +0000750 var allocIDs []uint32
751 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530752 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530753 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000754 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000755
npujarec5762e2020-01-01 14:08:48 +0530756 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
757 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000758 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530759
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530761 "intf-id": intfID,
762 "onu-id": onuID,
763 "uni-id": uniID,
764 "device-id": f.deviceHandler.device.Id,
765 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530766
Manikkaraj kb1d51442019-07-23 10:41:02 -0400767 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530768 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000769 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000770 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530771 log.Fields{
772 "path": tpPath,
773 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530774 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000775 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530776 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000777 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530778 log.Fields{
779 "error": err,
780 "tp-id": TpID,
781 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000782 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530783 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400784 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
785 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
786 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530787 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000788 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530789 log.Fields{
790 "uni": uni,
791 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530792 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530793 }
Gamze Abakafee36392019-10-03 11:17:24 +0000794
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700795 switch tpInst := techProfileInstance.(type) {
796 case *tp.TechProfile:
797 if UsMeterID != 0 {
798 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
799 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
800 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000801 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700802 log.Fields{
803 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700804 "onu-id": onuID,
805 "uni-id": uniID,
806 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700807 "meter-id": UsMeterID,
808 "device-id": f.deviceHandler.device.Id})
809 return 0, nil, nil
810 }
811 }
812 if DsMeterID != 0 {
813 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
814 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
815 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700817 log.Fields{
818 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700819 "onu-id": onuID,
820 "uni-id": uniID,
821 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700822 "meter-id": DsMeterID,
823 "device-id": f.deviceHandler.device.Id})
824 return 0, nil, nil
825 }
826 }
827 allocID := tpInst.UsScheduler.AllocID
828 for _, gem := range tpInst.UpstreamGemPortAttributeList {
829 gemPortIDs = append(gemPortIDs, gem.GemportID)
830 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700831 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000832
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700833 if tpInstanceExists {
834 return allocID, gemPortIDs, techProfileInstance
835 }
836
837 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700838 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700839 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700842 "intf-id": intfID,
843 "onu-id": onuID,
844 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700845 "alloc-ids": allocIDs,
846 "gemports": allgemPortIDs,
847 "device-id": f.deviceHandler.device.Id})
848 // Send Tconts and GEM ports to KV store
849 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530850 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700851 case *tp.EponProfile:
852 // CreateSchedulerQueues for EPON needs to be implemented here
853 // when voltha-protos for EPON is completed.
854 allocID := tpInst.AllocID
855 for _, gem := range tpInst.UpstreamQueueAttributeList {
856 gemPortIDs = append(gemPortIDs, gem.GemportID)
857 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700858 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700859
860 if tpInstanceExists {
861 return allocID, gemPortIDs, techProfileInstance
862 }
863
864 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700865 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000867 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700868 log.Fields{
869 "alloc-ids": allocIDs,
870 "gemports": allgemPortIDs,
871 "device-id": f.deviceHandler.device.Id})
872 // Send Tconts and GEM ports to KV store
873 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
874 return allocID, gemPortIDs, techProfileInstance
875 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700877 log.Fields{
878 "tpInst": tpInst})
879 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530880 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530881}
882
npujarec5762e2020-01-01 14:08:48 +0530883func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530884
Neha Sharma96b7bf22020-06-15 10:37:32 +0000885 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530886 log.Fields{
887 "intf-id": intfID,
888 "onu-id": onuID,
889 "uni-id": uniID,
890 "alloc-id": allocID,
891 "gemport-ids": gemPortIDs,
892 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530893 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530894 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000895 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 +0530896 }
npujarec5762e2020-01-01 14:08:48 +0530897 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000898 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 +0530899 }
npujarec5762e2020-01-01 14:08:48 +0530900 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000901 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 +0000902 } else {
903 //add to gem to uni cache
904 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530905 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 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 -0400907 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530908 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400909 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530910}
911
Esin Karamandf392e12020-12-16 13:33:09 +0000912//addGemPortUniAssociationsToCache
913func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
914 for _, gemPortID := range gemPortIDs {
915 key := gemPortKey{
916 intfID: intfID,
917 gemPort: gemPortID,
918 }
919 f.toGemToUniMap(ctx, key, onuID, uniID)
920 }
921 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
922 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
923}
924
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000926 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530927 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000928 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700929 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400930 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000931 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530932 log.Fields{
933 "intf-id": intfID,
934 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530935 }
936 }
937 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400938 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530939 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530940 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800941 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530942 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
943 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530944 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000945 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530946 log.Fields{
947 "numofTech": tpCount,
948 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
949 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530950 return nil
951}
952
Gamze Abaka7650be62021-02-26 10:50:36 +0000953func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
954 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000955 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530956 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000957 "uplinkClassifier": flowContext.classifier,
958 "uplinkAction": flowContext.action})
959 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530960 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530961}
962
Gamze Abaka7650be62021-02-26 10:50:36 +0000963func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
964 downlinkClassifier := flowContext.classifier
965 downlinkAction := flowContext.action
966
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700967 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000968 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530969 log.Fields{
970 "downlinkClassifier": downlinkClassifier,
971 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400972 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
973 if vlan, exists := downlinkClassifier[VlanVid]; exists {
974 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700975 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000976 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000977 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530978 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000979 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530980 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000981 "onu-id": flowContext.onuID,
982 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800983 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400984 }
985 }
986 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530987 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400988
Manikkaraj k884c1242019-04-11 16:26:42 +0530989 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700990 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400991 // vlan_vid is a uint32. must be type asserted as such or conversion fails
992 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530993 if ok {
994 downlinkAction[VlanVid] = dlClVid & 0xfff
995 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530996 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530997 "reason": "failed-to-convert-vlanid-classifier",
998 "vlan-id": VlanVid,
999 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +05301000 }
1001
Gamze Abaka7650be62021-02-26 10:50:36 +00001002 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301003}
1004
Gamze Abaka7650be62021-02-26 10:50:36 +00001005func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001006
1007 var inverseDirection string
1008 if direction == Upstream {
1009 inverseDirection = Downstream
1010 } else {
1011 inverseDirection = Upstream
1012 }
1013
Gamze Abaka7650be62021-02-26 10:50:36 +00001014 intfID := flowContext.intfID
1015 onuID := flowContext.onuID
1016 uniID := flowContext.uniID
1017 classifier := flowContext.classifier
1018 action := flowContext.action
1019 allocID := flowContext.allocID
1020 gemPortID := flowContext.gemPortID
1021 tpID := flowContext.tpID
1022 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301024 log.Fields{
1025 "intf-id": intfID,
1026 "onu-id": onuID,
1027 "uni-id": uniID,
1028 "device-id": f.deviceHandler.device.Id,
1029 "classifier": classifier,
1030 "action": action,
1031 "direction": direction,
1032 "alloc-id": allocID,
1033 "gemport-id": gemPortID,
1034 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001035
1036 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001037 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301038 log.Fields{
1039 "device-id": f.deviceHandler.device.Id,
1040 "intf-id": intfID,
1041 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301043 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001044 classifierProto, err := makeOpenOltClassifierField(classifier)
1045 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301046 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301047 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001048 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301049 log.Fields{
1050 "classifier": *classifierProto,
1051 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001052 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001053 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301054 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301055 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001056 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301057 log.Fields{
1058 "action": *actionProto,
1059 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301061 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301062 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001063 log.Fields{
1064 "classifier": classifier,
1065 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301066 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001067 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301068 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001069
1070 // Get symmetric flowID if it exists
1071 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1072 // symmetric flow earlier
1073 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1074 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1075 f.subscriberDataPathFlowIDMapLock.RLock()
1076 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1077 f.subscriberDataPathFlowIDMapLock.RUnlock()
1078
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001079 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001080 OnuId: int32(onuID),
1081 UniId: int32(uniID),
1082 FlowId: logicalFlow.Id,
1083 FlowType: direction,
1084 AllocId: int32(allocID),
1085 NetworkIntfId: int32(networkIntfID),
1086 GemportId: int32(gemPortID),
1087 Classifier: classifierProto,
1088 Action: actionProto,
1089 Priority: int32(logicalFlow.Priority),
1090 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001091 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001092 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001093 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1094 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001095 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001096 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001097 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001099 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301100 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001101 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301102 log.Fields{"direction": direction,
1103 "device-id": f.deviceHandler.device.Id,
1104 "flow": flow,
1105 "intf-id": intfID,
1106 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001107 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1108 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1109 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301110 log.Fields{
1111 "flow": flow,
1112 "device-id": f.deviceHandler.device.Id,
1113 "intf-id": intfID,
1114 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001115 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001116
1117 // Update the current flowID to the map
1118 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1119 f.subscriberDataPathFlowIDMapLock.Lock()
1120 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1121 f.subscriberDataPathFlowIDMapLock.Unlock()
1122
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301124}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001125
Gamze Abaka7650be62021-02-26 10:50:36 +00001126func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1127
1128 intfID := flowContext.intfID
1129 onuID := flowContext.onuID
1130 uniID := flowContext.uniID
1131 logicalFlow := flowContext.logicalFlow
1132 classifier := flowContext.classifier
1133 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301134
Neha Sharma96b7bf22020-06-15 10:37:32 +00001135 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301136 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301137 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001138 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301139 "action": action,
1140 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301142 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301143
1144 // Clear the action map
1145 for k := range action {
1146 delete(action, k)
1147 }
1148
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001149 action[TrapToHost] = true
1150 classifier[UDPSrc] = uint32(68)
1151 classifier[UDPDst] = uint32(67)
1152 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001154 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001155 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301156 log.Fields{
1157 "device-id": f.deviceHandler.device.Id,
1158 "intf-id": intfID,
1159 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301161 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162
Neha Sharma96b7bf22020-06-15 10:37:32 +00001163 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301164 log.Fields{
1165 "ul_classifier": classifier,
1166 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001167 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301168 "intf-id": intfID,
1169 "onu-id": onuID,
1170 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301171
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 classifierProto, err := makeOpenOltClassifierField(classifier)
1173 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301174 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301175 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001176 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001177 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001178 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301179 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301180 }
1181
David K. Bainbridge794735f2020-02-11 21:01:37 -08001182 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001183 OnuId: int32(onuID),
1184 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001185 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001186 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001187 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001188 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001189 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301190 Classifier: classifierProto,
1191 Action: actionProto,
1192 Priority: int32(logicalFlow.Priority),
1193 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001194 PortNo: flowContext.portNo,
1195 TechProfileId: flowContext.tpID,
1196 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1197 PbitToGemport: flowContext.pbitToGem,
1198 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001199 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001201 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301204 log.Fields{
1205 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001206 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301207 "intf-id": intfID,
1208 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1210 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 +05301211 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1212 log.Fields{
1213 "flow": dhcpFlow,
1214 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301215 }
1216
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301218}
1219
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001221func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1222 delete(flowContext.classifier, VlanVid)
1223 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001224}
1225
1226//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001227func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1228
1229 intfID := flowContext.intfID
1230 onuID := flowContext.onuID
1231 uniID := flowContext.uniID
1232 logicalFlow := flowContext.logicalFlow
1233 classifier := flowContext.classifier
1234 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235
Neha Sharma96b7bf22020-06-15 10:37:32 +00001236 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301238 return olterrors.NewErrNotFound("nni-interface-id",
1239 log.Fields{
1240 "classifier": classifier,
1241 "action": action,
1242 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001244 }
1245
1246 // Clear the action map
1247 for k := range action {
1248 delete(action, k)
1249 }
1250
1251 action[TrapToHost] = true
1252 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001253
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001254 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001255 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257 }
1258
Neha Sharma96b7bf22020-06-15 10:37:32 +00001259 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301260 log.Fields{
1261 "ul_classifier": classifier,
1262 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001263 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301264 "device-id": f.deviceHandler.device.Id,
1265 "intf-id": intfID,
1266 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267
David K. Bainbridge794735f2020-02-11 21:01:37 -08001268 classifierProto, err := makeOpenOltClassifierField(classifier)
1269 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301270 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001271 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001272 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301273 log.Fields{
1274 "classifier": *classifierProto,
1275 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001276 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301278 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279 }
1280
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282 OnuId: int32(onuID),
1283 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001284 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001286 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001288 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001289 Classifier: classifierProto,
1290 Action: actionProto,
1291 Priority: int32(logicalFlow.Priority),
1292 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001293 PortNo: flowContext.portNo,
1294 TechProfileId: flowContext.tpID,
1295 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1296 PbitToGemport: flowContext.pbitToGem,
1297 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001298 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001299
David K. Bainbridge794735f2020-02-11 21:01:37 -08001300 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001301 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 -08001302 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001303
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001304 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1305 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 +05301306 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 +00001307 }
1308
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001310}
1311
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001312// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001313func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1314 intfID := flowContext.intfID
1315 onuID := flowContext.onuID
1316 uniID := flowContext.uniID
1317 portNo := flowContext.portNo
1318 allocID := flowContext.allocID
1319 gemPortID := flowContext.gemPortID
1320 logicalFlow := flowContext.logicalFlow
1321 classifier := flowContext.classifier
1322 action := flowContext.action
1323
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301325 log.Fields{
1326 "intf-id": intfID,
1327 "onu-id": onuID,
1328 "port-no": portNo,
1329 "alloc-id": allocID,
1330 "gemport-id": gemPortID,
1331 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001332 "flow": logicalFlow,
1333 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301334
1335 uplinkClassifier := make(map[string]interface{})
1336 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301337
manikkaraj kbf256be2019-03-25 00:13:48 +05301338 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001339 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001340 uplinkClassifier[PacketTagType] = SingleTag
1341 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001342 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001344 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001345 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001346 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301347 "device-id": f.deviceHandler.device.Id,
1348 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001349 "intf-id": intfID,
1350 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001351 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301352 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001353 //Add Uplink EthType Flow
1354 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301355 log.Fields{
1356 "ul_classifier": uplinkClassifier,
1357 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001358 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301359 "device-id": f.deviceHandler.device.Id,
1360 "intf-id": intfID,
1361 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301362
David K. Bainbridge794735f2020-02-11 21:01:37 -08001363 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1364 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301365 return olterrors.NewErrInvalidValue(log.Fields{
1366 "classifier": uplinkClassifier,
1367 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301368 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001369 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301370 log.Fields{
1371 "classifier": *classifierProto,
1372 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001373 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001374 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301375 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301376 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001377 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301378 log.Fields{
1379 "action": *actionProto,
1380 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001381 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301382 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301383 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301385 "action": action,
1386 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 }
1389
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001391 OnuId: int32(onuID),
1392 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001393 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001394 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001395 AllocId: int32(allocID),
1396 NetworkIntfId: int32(networkIntfID),
1397 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301398 Classifier: classifierProto,
1399 Action: actionProto,
1400 Priority: int32(logicalFlow.Priority),
1401 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001402 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001403 TechProfileId: flowContext.tpID,
1404 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1405 PbitToGemport: flowContext.pbitToGem,
1406 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001407 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001409 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001410 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001411 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301412 log.Fields{
1413 "device-id": f.deviceHandler.device.Id,
1414 "onu-id": onuID,
1415 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001416 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301417 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001418 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1419 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 +05301420 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1421 log.Fields{
1422 "flow": upstreamFlow,
1423 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301424 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001439 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1440 vid := uint32(metadata)
1441 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001442 classifier.IVid = vid
1443 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301444 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301445 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301447 classifier.OPbits = vlanPcp
1448 } else {
1449 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001451 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1452 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1453 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1454 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001455 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001456 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1457 classifier.PktTagType = pktTagType
1458
1459 switch pktTagType {
1460 case SingleTag:
1461 case DoubleTag:
1462 case Untagged:
1463 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001464 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301465 }
1466 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001467 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301468}
1469
Gamze Abaka724d0852020-03-18 12:10:24 +00001470func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001471 var actionCmd openoltpb2.ActionCmd
1472 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301473 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001474 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301475 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001476 if _, ok := actionInfo[VlanPcp]; ok {
1477 action.Cmd.RemarkInnerPbits = true
1478 action.IPbits = actionInfo[VlanPcp].(uint32)
1479 if _, ok := actionInfo[VlanVid]; ok {
1480 action.Cmd.TranslateInnerTag = true
1481 action.IVid = actionInfo[VlanVid].(uint32)
1482 }
1483 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001484 } else if _, ok := actionInfo[PushVlan]; ok {
1485 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301486 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001487 if _, ok := actionInfo[VlanPcp]; ok {
1488 action.OPbits = actionInfo[VlanPcp].(uint32)
1489 action.Cmd.RemarkOuterPbits = true
1490 if _, ok := classifierInfo[VlanVid]; ok {
1491 action.IVid = classifierInfo[VlanVid].(uint32)
1492 action.Cmd.TranslateInnerTag = true
1493 }
1494 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001495 } else if _, ok := actionInfo[TrapToHost]; ok {
1496 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301497 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001498 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301499 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001500 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301501}
1502
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001503// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001504func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1505 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301506}
1507
Gamze Abakafee36392019-10-03 11:17:24 +00001508// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001509func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301510 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001511 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1512
Gamze Abakafee36392019-10-03 11:17:24 +00001513 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301514 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001515 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301516 // return err
1517 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001518 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001519 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001520 }
1521 return nil
1522}
1523
1524// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301525func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001526 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001527 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001528 }
npujarec5762e2020-01-01 14:08:48 +05301529 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301530 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1531 log.Fields{
1532 "tp-id": tpID,
1533 "uni-port-name": uniPortName,
1534 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001535 }
1536 return nil
1537}
1538
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001540
1541 var intfID uint32
1542 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1543 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1544 */
1545 if deviceFlow.AccessIntfId != -1 {
1546 intfID = uint32(deviceFlow.AccessIntfId)
1547 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001548 // We need to log the valid interface ID.
1549 // 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 +00001550 intfID = uint32(deviceFlow.NetworkIntfId)
1551 }
1552
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301554 "flow": *deviceFlow,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001557 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001558
1559 st, _ := status.FromError(err)
1560 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001562 "err": err,
1563 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301564 "device-id": f.deviceHandler.device.Id,
1565 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301567 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001568
1569 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001570 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301571 log.Fields{"err": err,
1572 "device-flow": deviceFlow,
1573 "device-id": f.deviceHandler.device.Id,
1574 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001575 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001576 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "flow": *deviceFlow,
1580 "device-id": f.deviceHandler.device.Id,
1581 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001582
1583 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1584 if deviceFlow.AccessIntfId != -1 {
1585 // No need to register the flow if it is a trap on nni flow.
1586 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1587 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1588 return err
1589 }
1590 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001591 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001592}
1593
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1595 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301596 log.Fields{
1597 "flow": *deviceFlow,
1598 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001599 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001600 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001601 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301603 log.Fields{
1604 "err": err,
1605 "deviceFlow": deviceFlow,
1606 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001607 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001609 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001610 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001611
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001614 "of-flow-id": ofFlowID,
1615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301619}
1620
David K. Bainbridge794735f2020-02-11 21:01:37 -08001621func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001622
1623 classifierInfo := make(map[string]interface{})
1624 actionInfo := make(map[string]interface{})
1625
1626 classifierInfo[EthType] = uint32(LldpEthType)
1627 classifierInfo[PacketTagType] = Untagged
1628 actionInfo[TrapToHost] = true
1629
1630 // LLDP flow is installed to trap LLDP packets on the NNI port.
1631 // We manage flow_id resource pool on per PON port basis.
1632 // Since this situation is tricky, as a hack, we pass the NNI port
1633 // index (network_intf_id) as PON port Index for the flow_id resource
1634 // pool. Also, there is no ONU Id available for trapping LLDP packets
1635 // on NNI port, use onu_id as -1 (invalid)
1636 // ****************** CAVEAT *******************
1637 // This logic works if the NNI Port Id falls within the same valid
1638 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1639 // we need to have a re-look at this.
1640 // *********************************************
1641
1642 var onuID = -1
1643 var uniID = -1
1644 var gemPortID = -1
1645
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301648 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001649 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001650 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001652 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001653 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001654
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1656 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301657 return olterrors.NewErrInvalidValue(
1658 log.Fields{
1659 "classifier": classifierInfo,
1660 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001661 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "classifier": *classifierProto,
1665 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001666 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001667 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301668 return olterrors.NewErrInvalidValue(
1669 log.Fields{
1670 "action": actionInfo,
1671 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001672 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "action": *actionProto,
1676 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001677
1678 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1679 OnuId: int32(onuID), // OnuId not required
1680 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001681 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001682 FlowType: Downstream,
1683 NetworkIntfId: int32(networkInterfaceID),
1684 GemportId: int32(gemPortID),
1685 Classifier: classifierProto,
1686 Action: actionProto,
1687 Priority: int32(flow.Priority),
1688 Cookie: flow.Cookie,
1689 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001690 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001691 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "flow": downstreamflow,
1694 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001695 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001696 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301697 log.Fields{
1698 "device-id": f.deviceHandler.device.Id,
1699 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001700 "flow-id": flow.Id})
1701 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1702 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1703 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301704 log.Fields{
1705 "flow": downstreamflow,
1706 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001707 }
1708 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301709}
1710
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001711func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1712 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001713}
1714
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001715//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001717 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1718 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1719 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001720 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301721 log.Fields{
1722 "intf-id": intfID,
1723 "onu-id": onuID,
1724 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001726 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301727 return nil, olterrors.NewErrNotFound("onu-child-device",
1728 log.Fields{
1729 "onu-id": onuID,
1730 "intf-id": intfID,
1731 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 }
1733 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1734 //better to ad the device to cache here.
1735 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1736 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001737 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301738 log.Fields{
1739 "intf-id": intfID,
1740 "onu-id": onuID,
1741 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001742 }
1743
1744 return onuDev.(*OnuDevice), nil
1745}
1746
1747//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001748func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1749 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301750 log.Fields{
1751 "pon-port": intfID,
1752 "onu-id": onuID,
1753 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001754 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001756 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301757 return nil, olterrors.NewErrNotFound("onu",
1758 log.Fields{
1759 "interface-id": parentPortNo,
1760 "onu-id": onuID,
1761 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001762 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301763 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301765 log.Fields{
1766 "device-id": f.deviceHandler.device.Id,
1767 "child_device_id": onuDevice.Id,
1768 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301769 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301770}
1771
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1773 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301774 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301776 log.Fields{
1777 "intf-id": intfID,
1778 "onu-id": onuID,
1779 "uni-id": uniID,
1780 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301782 }
1783
1784 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301786 log.Fields{
1787 "msg": *delGemPortMsg,
1788 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001789 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301790 delGemPortMsg,
1791 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001792 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001793 onuDev.deviceType,
1794 onuDev.deviceID,
1795 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301796 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1797 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001798 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301799 "to-adapter": onuDev.deviceType,
1800 "onu-id": onuDev.deviceID,
1801 "proxyDeviceID": onuDev.proxyDeviceID,
1802 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301803 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301805 log.Fields{
1806 "msg": delGemPortMsg,
1807 "from-adapter": f.deviceHandler.device.Type,
1808 "to-adapter": onuDev.deviceType,
1809 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301810 return nil
1811}
1812
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1814 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301815 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001816 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301817 log.Fields{
1818 "intf-id": intfID,
1819 "onu-id": onuID,
1820 "uni-id": uniID,
1821 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001822 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301823 }
1824
1825 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301827 log.Fields{
1828 "msg": *delTcontMsg,
1829 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001830 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301831 delTcontMsg,
1832 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001833 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001834 onuDev.deviceType,
1835 onuDev.deviceID,
1836 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301837 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1838 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001839 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301840 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1841 "proxyDeviceID": onuDev.proxyDeviceID,
1842 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301843 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001844 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301845 log.Fields{
1846 "msg": delTcontMsg,
1847 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 return nil
1849}
1850
Girish Gowdrac3037402020-01-22 20:29:53 +05301851// Once the gemport is released for a given onu, it also has to be cleared from local cache
1852// which was used for deriving the gemport->logicalPortNo during packet-in.
1853// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1854// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001856
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001857 f.onuGemInfoLock.Lock()
1858 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001859
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301861 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001862 "gem-port-id": gemPortID,
1863 "intf-id": intfID,
1864 "onu-id": onuID,
1865 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001866 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001867
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001868 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001869deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001870 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301871 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001872 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301873 // If the gemport is found, delete it from local cache.
1874 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001875 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1876 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001877 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301878 log.Fields{
1879 "intf-id": intfID,
1880 "onu-id": onuID,
1881 "deletedgemport-id": gemPortID,
1882 "gemports": onu.GemPorts,
1883 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001884 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301885 }
1886 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001887 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301888 }
1889 }
1890}
1891
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301892//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001893// nolint: gocyclo
Girish Gowdraa482f272021-03-24 23:04:19 -07001894func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001895 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001896
Girish Gowdraa482f272021-03-24 23:04:19 -07001897 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1898 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001899 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1900 log.Fields{
1901 "tpPath": tpPath,
1902 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001903 techprofileInst, err := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001904 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1905 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1906 log.Fields{
1907 "tp-id": tpID,
1908 "path": tpPath}, err)
1909 }
1910
1911 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1912
1913 if used {
1914 f.flowsUsedByGemPortKey.Lock()
1915 defer f.flowsUsedByGemPortKey.Unlock()
1916
1917 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1918 for i, flowIDinMap := range flowIDs {
1919 if flowIDinMap == flowID {
1920 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1921 // everytime flowsUsedByGemPort cache is updated the same should be updated
1922 // in kv store by calling UpdateFlowIDsForGem
1923 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
Girish Gowdraa482f272021-03-24 23:04:19 -07001924 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 return err
1926 }
1927 break
1928 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001929 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1931 log.Fields{
1932 "gemport-id": gemPortID,
1933 "usedByFlows": flowIDs,
1934 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001935
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001936 return nil
1937 }
1938 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 -07001939 f.resourceMgr.RemoveGemPortIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1941 // 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 -07001942 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), intfID)
Esin Karamandf392e12020-12-16 13:33:09 +00001943 // also clear gem to uni cache
1944 f.removeFromGemToUniMap(gemPortKey{
Girish Gowdraa482f272021-03-24 23:04:19 -07001945 intfID: intfID,
Esin Karamandf392e12020-12-16 13:33:09 +00001946 gemPort: uint32(gemPortID),
1947 })
Girish Gowdraa482f272021-03-24 23:04:19 -07001948 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001949
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001950 f.onuIdsLock.Lock() // TODO: What is this lock?
1951
1952 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1953 // by calling DeleteFlowIDsForGem
1954 f.flowsUsedByGemPortKey.Lock()
1955 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1956 f.flowsUsedByGemPortKey.Unlock()
Girish Gowdraa482f272021-03-24 23:04:19 -07001957 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1958 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001959
1960 f.onuIdsLock.Unlock()
1961
1962 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001963 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001964 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1965 log.Fields{
1966 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001967 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001968 "onu-id": onuID,
1969 "uni-id": uniID,
1970 "device-id": f.deviceHandler.device.Id,
1971 "gemport-id": gemPortID})
1972 }
1973 switch techprofileInst := techprofileInst.(type) {
1974 case *tp.TechProfile:
Gamze Abakacb0e6772021-06-10 08:32:12 +00001975 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 if !ok {
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 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 -07001984 logger.Warn(ctx, err)
1985 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001986 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 -07001987 logger.Warn(ctx, err)
1988 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001989 }
1990 case *tp.EponProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001991 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001992 logger.Warn(ctx, err)
1993 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001994 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001995 logger.Warn(ctx, err)
1996 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001997 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001998 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001999 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002000 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302001 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002002 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302003 "onu-id": onuID,
2004 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002005 "device-id": f.deviceHandler.device.Id,
2006 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00002007 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002008 default:
2009 logger.Errorw(ctx, "error-unknown-tech",
2010 log.Fields{
2011 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002012 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002013
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302014 return nil
2015}
2016
David K. Bainbridge794735f2020-02-11 21:01:37 -08002017// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002018func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002019 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002020 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302021 log.Fields{
2022 "flowDirection": flowDirection,
2023 "flow": *flow,
2024 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002025
2026 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002028 }
2029
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302030 classifierInfo := make(map[string]interface{})
2031
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302033 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002034 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002035 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302036 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302037
David K. Bainbridge794735f2020-02-11 21:01:37 -08002038 onuID := int32(onu)
2039 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302040
2041 for _, field := range flows.GetOfbFields(flow) {
2042 if field.Type == flows.IP_PROTO {
2043 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002044 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302045 }
2046 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002047 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302048 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002049 "flow-id": flow.Id,
2050 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302051 "onu-id": onuID,
2052 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302053
2054 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2055 onuID = -1
2056 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002057 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2058 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002059 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002061 log.Fields{
2062 "port-number": inPort,
2063 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002064 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002065 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302066 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002067 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2068 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})
2069 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2070 }
2071 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2072 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2073 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2074 return err
2075 }
2076 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2077 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2078 return err
2079 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002080 tpID, err := getTpIDFromFlow(ctx, flow)
2081 if err != nil {
2082 return olterrors.NewErrNotFound("tp-id",
2083 log.Fields{
2084 "flow": flow,
2085 "intf-id": Intf,
2086 "onu-id": onuID,
2087 "uni-id": uniID,
2088 "device-id": f.deviceHandler.device.Id}, err)
2089 }
2090
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002091 if !flowInfo.Flow.ReplicateFlow {
Girish Gowdra82c80982021-03-26 16:22:02 -07002092 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 -08002093 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002094 "flow-id": flow.Id,
2095 "stored-flow": flowInfo.Flow,
2096 "device-id": f.deviceHandler.device.Id,
2097 "stored-flow-id": flowInfo.Flow.FlowId,
2098 "onu-id": onuID,
2099 "intf": Intf,
Girish Gowdra82c80982021-03-26 16:22:02 -07002100 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002101 })
2102 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302103 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002104 } else {
2105 gems := make([]uint32, 0)
2106 for _, gem := range flowInfo.Flow.PbitToGemport {
2107 gems = appendUnique32bit(gems, gem)
2108 }
2109 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2110 for _, gem := range gems {
Girish Gowdra82c80982021-03-26 16:22:02 -07002111 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 -08002112 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002113 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002114 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002115 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002116 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002117 "onu-id": onuID,
2118 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002119 "gem": gem,
Girish Gowdra82c80982021-03-26 16:22:02 -07002120 "err": err,
Matteo Scandolo92186242020-06-12 10:54:18 -07002121 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002122 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302123 }
2124 }
2125 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002126
2127 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2128 if isDatapathFlow(flow) {
2129 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2130 var inverseDirection string
2131 if flowDirection == Upstream {
2132 inverseDirection = Downstream
2133 } else {
2134 inverseDirection = Upstream
2135 }
2136
2137 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002138 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002139 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002140 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002141 }
2142 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002143 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2144 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2145 return err
2146 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002147 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002148}
2149
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002150//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002151func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002152
Matteo Scandolof16389e2021-05-18 00:47:08 +00002153 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302154 var direction string
2155 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002156
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302157 for _, action := range flows.GetActions(flow) {
2158 if action.Type == flows.OUTPUT {
2159 if out := action.GetOutput(); out != nil {
2160 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002161 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302162 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002164 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002165 }
2166 }
2167 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002168
2169 if flows.HasGroup(flow) {
2170 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002171 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002172 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302173 direction = Upstream
2174 } else {
2175 direction = Downstream
2176 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302177
Girish Gowdracefae192020-03-19 18:14:10 -07002178 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002179 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002180
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002181 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002182}
2183
Esin Karamanae41e2b2019-12-17 18:13:13 +00002184//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2185func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2186 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2187 if ethType, ok := classifierInfo[EthType]; ok {
2188 if ethType.(uint32) == IPv4EthType {
2189 if ipProto, ok := classifierInfo[IPProto]; ok {
2190 if ipProto.(uint32) == IgmpProto {
2191 return true
2192 }
2193 }
2194 }
2195 }
2196 }
2197 return false
2198}
2199
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002200// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2201func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2202 // Step1 : Fill flowControlBlock
2203 // Step2 : Push the flowControlBlock to ONU channel
2204 // Step3 : Wait on response channel for response
2205 // Step4 : Return error value
2206 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2207 errChan := make(chan error)
2208 flowCb := flowControlBlock{
2209 ctx: ctx,
2210 addFlow: addFlow,
2211 flow: flow,
2212 flowMetadata: flowMetadata,
2213 errChan: &errChan,
2214 }
2215 inPort, outPort := getPorts(flow)
2216 var onuID uint32
2217 if inPort != InvalidPort && outPort != InvalidPort {
2218 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2219 }
2220 // inPort or outPort is InvalidPort for trap-from-nni flows.
2221 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2222 // Send the flowCb on the ONU flow channel
2223 f.incomingFlows[onuID] <- flowCb
2224 // Wait on the channel for flow handlers return value
2225 err := <-errChan
2226 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2227 return err
2228}
2229
2230// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2231// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2232func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2233 for {
2234 // block on the channel to receive an incoming flow
2235 // process the flow completely before proceeding to handle the next flow
2236 flowCb := <-subscriberFlowChannel
2237 if flowCb.addFlow {
2238 logger.Debugw(flowCb.ctx, "adding-flow",
2239 log.Fields{"device-id": f.deviceHandler.device.Id,
2240 "flowToAdd": flowCb.flow})
2241 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2242 // Pass the return value over the return channel
2243 *flowCb.errChan <- err
2244 } else {
2245 logger.Debugw(flowCb.ctx, "removing-flow",
2246 log.Fields{"device-id": f.deviceHandler.device.Id,
2247 "flowToRemove": flowCb.flow})
2248 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2249 // Pass the return value over the return channel
2250 *flowCb.errChan <- err
2251 }
2252 }
2253}
2254
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002255// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302256// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002257func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002258 classifierInfo := make(map[string]interface{})
2259 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002260 var UsMeterID uint32
2261 var DsMeterID uint32
2262
Neha Sharma96b7bf22020-06-15 10:37:32 +00002263 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302264 log.Fields{
2265 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002266 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002267 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002268
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002270 if err != nil {
2271 // Error logging is already done in the called function
2272 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002273 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302274 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002275
Esin Karamanccb714b2019-11-29 15:02:06 +00002276 if flows.HasGroup(flow) {
2277 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002278 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002279 }
2280
manikkaraj k17652a72019-05-06 09:06:36 -04002281 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002283 if err != nil {
2284 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002285 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002286 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002287
Neha Sharma96b7bf22020-06-15 10:37:32 +00002288 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302289 log.Fields{
2290 "classifierinfo_inport": classifierInfo[InPort],
2291 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002292 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002293
Humera Kouser94d7a842019-08-25 19:04:32 -04002294 if ethType, ok := classifierInfo[EthType]; ok {
2295 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002297 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002298 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002299 if ethType.(uint32) == PPPoEDEthType {
2300 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2301 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2302 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2303 }
2304 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002305 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002306 if ipProto, ok := classifierInfo[IPProto]; ok {
2307 if ipProto.(uint32) == IPProtoDhcp {
2308 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302309 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002310 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002311 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002312 }
2313 }
2314 }
2315 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002316 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002318 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002319 }
A R Karthick1f85b802019-10-11 05:06:05 +00002320
npujarec5762e2020-01-01 14:08:48 +05302321 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002322
Neha Sharma96b7bf22020-06-15 10:37:32 +00002323 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002324 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302325 return olterrors.NewErrNotFound("tpid-for-flow",
2326 log.Fields{
2327 "flow": flow,
2328 "intf-id": IntfID,
2329 "onu-id": onuID,
2330 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002331 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002332 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302333 log.Fields{
2334 "tp-id": TpID,
2335 "intf-id": intfID,
2336 "onu-id": onuID,
2337 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002338 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002339 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002341 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002342 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002343 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002344
2345 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002346 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002347}
Girish Gowdra3d633032019-12-10 16:37:05 +05302348
Esin Karamanccb714b2019-11-29 15:02:06 +00002349// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002350func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002351 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302353 "classifier-info": classifierInfo,
2354 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002355
Esin Karaman65409d82020-03-18 10:58:18 +00002356 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002357 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002358 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002359 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002360
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002361 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002362
David K. Bainbridge794735f2020-02-11 21:01:37 -08002363 onuID := NoneOnuID
2364 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002365
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002366 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002367 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002368 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002369 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002370 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2371 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002372 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002373 }
2374 groupID := actionInfo[GroupID].(uint32)
2375 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002376 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002377 FlowType: Multicast,
2378 NetworkIntfId: int32(networkInterfaceID),
2379 GroupId: groupID,
2380 Classifier: classifierProto,
2381 Priority: int32(flow.Priority),
2382 Cookie: flow.Cookie}
2383
Kent Hagermane6ff1012020-07-14 15:07:53 -04002384 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002385 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002386 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002388 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002389 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002390 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002391 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002392 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002393 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002394 //cached group can be removed now
2395 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2396 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2397 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002398 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002399
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002400 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2401 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2402 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002403 }
2404 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002405}
2406
Esin Karaman65409d82020-03-18 10:58:18 +00002407//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2408func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2409 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002411 if err != nil {
2412 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2413 }
2414 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002415 }
Esin Karaman65409d82020-03-18 10:58:18 +00002416 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302417 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002418 if e == nil && len(nniPorts) > 0 {
2419 return nniPorts[0], nil
2420 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302421 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002422}
2423
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002424//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002426
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302428 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302430 log.Fields{
2431 "intf-id": intfID,
2432 "onu-id": onuID,
2433 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002434 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302435 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002436 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002437
Neha Sharma96b7bf22020-06-15 10:37:32 +00002438 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002439 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002440 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002441 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002442 tpDownloadMsg,
2443 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002444 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002445 onuDev.deviceType,
2446 onuDev.deviceID,
2447 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002448 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302449 return olterrors.NewErrCommunication("send-techprofile-download-request",
2450 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002451 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302452 "to-adapter": onuDev.deviceType,
2453 "onu-id": onuDev.deviceID,
2454 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002455 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002456 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302457 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302458}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002459
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302460//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002461func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302462
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002463 f.onuGemInfoLock.Lock()
2464 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002465 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002466 // If the ONU already exists in onuGemInfo list, nothing to do
2467 for _, onu := range onugem {
2468 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2469 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2470 log.Fields{"onuID": onuID,
2471 "serialNum": serialNum})
2472 return nil
2473 }
2474 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002475
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302476 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002477 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002478 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002479 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302480 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302482 log.Fields{
2483 "intf-id": intfID,
2484 "onu-id": onuID,
2485 "serial-num": serialNum,
2486 "onu": onu,
2487 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002488 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002489}
2490
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302491//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302492func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002493
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002494 f.onuGemInfoLock.Lock()
2495 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002496
Neha Sharma96b7bf22020-06-15 10:37:32 +00002497 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302498 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002499 "gem-port-id": gemPort,
2500 "intf-id": intfID,
2501 "onu-id": onuID,
2502 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002503 "onu-gem": f.onuGemInfo})
2504 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302505 // update the gem to the local cache as well as to kv strore
2506 for idx, onu := range onugem {
2507 if onu.OnuID == onuID {
2508 // check if gem already exists , else update the cache and kvstore
2509 for _, gem := range onu.GemPorts {
2510 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302512 log.Fields{
2513 "gem": gemPort,
2514 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302515 return
2516 }
2517 }
2518 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002519 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002520 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302521 }
2522 }
npujarec5762e2020-01-01 14:08:48 +05302523 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302524 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002525 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302526 log.Fields{
2527 "intf-id": intfID,
2528 "onu-id": onuID,
2529 "gemPort": gemPort,
2530 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002531 return
2532 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002533 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302534 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002535 "gem-port-id": gemPort,
2536 "intf-id": intfID,
2537 "onu-id": onuID,
2538 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002539 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002540}
2541
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002542//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302543func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002545 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 var err error
2547
2548 if packetIn.IntfType == "pon" {
2549 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002550 // get onu and uni ids associated with the given pon and gem ports
2551 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002552 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002553 return logicalPortNum, err
2554 }
Esin Karamandf392e12020-12-16 13:33:09 +00002555 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2556
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002557 if packetIn.PortNo != 0 {
2558 logicalPortNum = packetIn.PortNo
2559 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002561 }
2562 // 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 +00002563 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002564 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002565 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002566 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002567
2568 if logger.V(log.DebugLevel) {
2569 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2570 log.Fields{
2571 "logical-port-num": logicalPortNum,
2572 "intf-type": packetIn.IntfType,
2573 "packet": hex.EncodeToString(packetIn.Pkt),
2574 })
2575 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002576 return logicalPortNum, nil
2577}
2578
Esin Karamandf392e12020-12-16 13:33:09 +00002579//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2580func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2581 key := gemPortKey{
2582 intfID: intfID,
2583 gemPort: gemPortID,
2584 }
2585 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2586 if ok {
2587 if len(uniPortInfo) > 1 {
2588 //return onu ID and uni port from the cache
2589 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2590 log.Fields{
2591 "intfID": intfID,
2592 "gemPortID": gemPortID,
2593 "onuID, uniID": uniPortInfo})
2594 return uniPortInfo[0], uniPortInfo[1], nil
2595 }
2596 }
2597 //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.
2598 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2599 if err == nil {
2600 f.toGemToUniMap(ctx, key, onuID, uniID)
2601 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2602 log.Fields{
2603 "gemPortKey": key,
2604 "onuID": onuID,
2605 "uniID": uniID})
2606 return onuID, uniID, nil
2607 }
2608 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2609 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2610 errors.New("no uni port found"))
2611}
2612
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002613//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002614func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002615 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002616
2617 ctag, priority, err := getCTagFromPacket(ctx, packet)
2618 if err != nil {
2619 return 0, err
2620 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302621
Esin Karaman7fb80c22020-07-16 14:23:33 +00002622 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002623 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002624 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002625 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002626 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302627 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002628 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302629 log.Fields{
2630 "pktinkey": pktInkey,
2631 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002632
2633 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302635 //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 +00002636 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 if err == nil {
2638 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002639 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302640 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002641 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002642 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302643 log.Fields{
2644 "pktinkey": pktInkey,
2645 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302646 return gemPortID, nil
2647 }
2648 }
Shrey Baid26912972020-04-16 21:02:31 +05302649 return uint32(0), olterrors.NewErrNotFound("gem-port",
2650 log.Fields{
2651 "pktinkey": pktInkey,
2652 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002653
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002654}
2655
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002656func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2657 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002658 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002659 classifier[PacketTagType] = DoubleTag
2660 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002661 /* We manage flowId resource pool on per PON port basis.
2662 Since this situation is tricky, as a hack, we pass the NNI port
2663 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002664 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002665 on NNI port, use onu_id as -1 (invalid)
2666 ****************** CAVEAT *******************
2667 This logic works if the NNI Port Id falls within the same valid
2668 range of PON Port Ids. If this doesn't work for some OLT Vendor
2669 we need to have a re-look at this.
2670 *********************************************
2671 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002672 onuID := -1
2673 uniID := -1
2674 gemPortID := -1
2675 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002676 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302677 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302678 return olterrors.NewErrNotFound("nni-intreface-id",
2679 log.Fields{
2680 "classifier": classifier,
2681 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002682 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302683 }
2684
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002685 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002687 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002688 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002689
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002690 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2691 log.Fields{
2692 "classifier": classifier,
2693 "action": action,
2694 "flowId": logicalFlow.Id,
2695 "intf-id": networkInterfaceID})
2696
David K. Bainbridge794735f2020-02-11 21:01:37 -08002697 classifierProto, err := makeOpenOltClassifierField(classifier)
2698 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002699 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002701 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002702 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002703 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002704 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002705 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002707 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2708 OnuId: int32(onuID), // OnuId not required
2709 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002710 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002711 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002712 AllocId: int32(allocID), // AllocId not used
2713 NetworkIntfId: int32(networkInterfaceID),
2714 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715 Classifier: classifierProto,
2716 Action: actionProto,
2717 Priority: int32(logicalFlow.Priority),
2718 Cookie: logicalFlow.Cookie,
2719 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002720 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002721 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002722 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002723 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002724 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2725 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2726 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002727 }
2728 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002729}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002730
Esin Karamanae41e2b2019-12-17 18:13:13 +00002731//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2732func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2733 var packetType string
2734 ovid, ivid := false, false
2735 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2736 vid := vlanID & VlanvIDMask
2737 if vid != ReservedVlan {
2738 ovid = true
2739 }
2740 }
2741 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2742 vid := uint32(metadata)
2743 if vid != ReservedVlan {
2744 ivid = true
2745 }
2746 }
2747 if ovid && ivid {
2748 packetType = DoubleTag
2749 } else if !ovid && !ivid {
2750 packetType = Untagged
2751 } else {
2752 packetType = SingleTag
2753 }
2754 return packetType
2755}
2756
2757//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002758func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002759 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002760 action := make(map[string]interface{})
2761 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2762 action[TrapToHost] = true
2763 /* We manage flowId resource pool on per PON port basis.
2764 Since this situation is tricky, as a hack, we pass the NNI port
2765 index (network_intf_id) as PON port Index for the flowId resource
2766 pool. Also, there is no ONU Id available for trapping packets
2767 on NNI port, use onu_id as -1 (invalid)
2768 ****************** CAVEAT *******************
2769 This logic works if the NNI Port Id falls within the same valid
2770 range of PON Port Ids. If this doesn't work for some OLT Vendor
2771 we need to have a re-look at this.
2772 *********************************************
2773 */
2774 onuID := -1
2775 uniID := -1
2776 gemPortID := -1
2777 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002778 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302780 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002781 "classifier": classifier,
2782 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002783 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002785 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002786 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002787 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002789
David K. Bainbridge794735f2020-02-11 21:01:37 -08002790 classifierProto, err := makeOpenOltClassifierField(classifier)
2791 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002792 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002793 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002794 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002795 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002796 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002797 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002798 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002799 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002800 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2801 OnuId: int32(onuID), // OnuId not required
2802 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002803 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002804 FlowType: Downstream,
2805 AllocId: int32(allocID), // AllocId not used
2806 NetworkIntfId: int32(networkInterfaceID),
2807 GemportId: int32(gemPortID), // GemportId not used
2808 Classifier: classifierProto,
2809 Action: actionProto,
2810 Priority: int32(logicalFlow.Priority),
2811 Cookie: logicalFlow.Cookie,
2812 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002813 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002814 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002815 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002816 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002817 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2818 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2819 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002820 }
2821 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002822}
2823
salmansiddiqui7ac62132019-08-22 03:58:50 +00002824func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2825 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302826 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002827 }
2828 if Dir == tp_pb.Direction_UPSTREAM {
2829 return "upstream", nil
2830 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2831 return "downstream", nil
2832 }
2833 return "", nil
2834}
2835
Kent Hagermane6ff1012020-07-14 15:07:53 -04002836// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302837func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002838 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002839 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002840 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002841 intfID := args[IntfID]
2842 onuID := args[OnuID]
2843 uniID := args[UniID]
2844 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002845 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002846 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 gemToAes := make(map[uint32]bool)
2848
2849 var attributes []tp.IGemPortAttribute
2850 var direction = tp_pb.Direction_UPSTREAM
2851 switch TpInst := TpInst.(type) {
2852 case *tp.TechProfile:
2853 if IsUpstream(actionInfo[Output].(uint32)) {
2854 attributes = TpInst.UpstreamGemPortAttributeList
2855 } else {
2856 attributes = TpInst.DownstreamGemPortAttributeList
2857 direction = tp_pb.Direction_DOWNSTREAM
2858 }
2859 default:
2860 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2861 return
2862 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002863
2864 if len(gemPorts) == 1 {
2865 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002866 gemPortID = gemPorts[0]
2867 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2869 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002870 pBitMap := attributes[idx].PbitMap
2871 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2872 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2873 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2874 // this pcp bit traffic.
2875 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2876 if pbitSet == pbit1 {
2877 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2878 pbitToGem[pcp] = gemID
2879 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002880 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002881 }
2882 }
2883 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002884 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2885 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2886 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2887 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002888 }
2889
Gamze Abaka7650be62021-02-26 10:50:36 +00002890 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2891 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2892
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 if ipProto, ok := classifierInfo[IPProto]; ok {
2894 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002895 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002896 "tp-id": tpID,
2897 "alloc-id": allocID,
2898 "intf-id": intfID,
2899 "onu-id": onuID,
2900 "uni-id": uniID,
2901 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002902 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002903 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002904 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 }
2906
Girish Gowdra32625212020-04-29 11:26:35 -07002907 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002908 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302909 log.Fields{
2910 "intf-id": intfID,
2911 "onu-id": onuID,
2912 "uni-id": uniID,
2913 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002914 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002915 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002916 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 return
2920 }
2921 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002922 if ethType.(uint32) == EapEthType {
2923 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002924 "intf-id": intfID,
2925 "onu-id": onuID,
2926 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002927 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002928 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002929 var vlanID uint32
2930 if val, ok := classifierInfo[VlanVid]; ok {
2931 vlanID = (val.(uint32)) & VlanvIDMask
2932 } else {
2933 vlanID = DefaultMgmtVlan
2934 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002935 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002936 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002937 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002938 } else if ethType.(uint32) == PPPoEDEthType {
2939 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2940 "tp-id": tpID,
2941 "alloc-id": allocID,
2942 "intf-id": intfID,
2943 "onu-id": onuID,
2944 "uni-id": uniID,
2945 })
2946 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002947 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002948 logger.Warn(ctx, err)
2949 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002950 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002951 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002952 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002953 "intf-id": intfID,
2954 "onu-id": onuID,
2955 "uni-id": uniID,
2956 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002957 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002958 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002959 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002961 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002963 "intf-id": intfID,
2964 "onu-id": onuID,
2965 "uni-id": uniID,
2966 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002967 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002968 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002969 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002970 }
2971 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002972 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302973 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002974 "intf-id": intfID,
2975 "onu-id": onuID,
2976 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302977 "classifier": classifierInfo,
2978 "action": actionInfo,
2979 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980 return
2981 }
2982 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002983 go func() {
2984 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2985 logger.Warn(ctx, err)
2986 }
2987 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002988}
2989
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002990func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2991 f.flowsUsedByGemPortKey.RLock()
2992 flowIDList := f.flowsUsedByGemPort[gemPortID]
2993 f.flowsUsedByGemPortKey.RUnlock()
2994 return len(flowIDList) > 1
2995
Gamze Abakafee36392019-10-03 11:17:24 +00002996}
2997
Gamze Abakacb0e6772021-06-10 08:32:12 +00002998func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
npujarec5762e2020-01-01 14:08:48 +05302999 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003000 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3001 for _, currentGemPort := range currentGemPorts {
3002 for _, tpGemPort := range tpGemPorts {
3003 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3004 return true, currentGemPort
3005 }
3006 }
3007 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003008 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
3009 return false, 0
3010}
Girish Gowdra54934262019-11-13 14:19:55 +05303011
Gamze Abakacb0e6772021-06-10 08:32:12 +00003012func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
3013 tpInst := sq.tpInst.(*tp.TechProfile)
3014 if tpInst.InstanceCtrl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3015 tpInstances := f.techprofile[sq.intfID].FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303017 for i := 0; i < len(tpInstances); i++ {
3018 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003019 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
3020 tpI.UsScheduler.AllocID == tpInst.UsScheduler.AllocID {
3021 logger.Debugw(ctx, "alloc-is-in-use",
3022 log.Fields{
3023 "device-id": f.deviceHandler.device.Id,
3024 "intfID": sq.intfID,
3025 "onuID": sq.onuID,
3026 "uniID": sq.uniID,
3027 "allocID": tpI.UsScheduler.AllocID,
3028 })
3029 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303030 }
3031 }
3032 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003033 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003034}
3035
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003037 for _, field := range flows.GetOfbFields(flow) {
3038 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003041 } else if field.Type == flows.ETH_DST {
3042 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003044 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003047 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003049 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003050 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303051 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003053 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003056 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003057 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003062 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003063 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003065 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003066 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003068 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003069 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003071 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003074 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 return
3077 }
3078 }
3079}
3080
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003082 for _, action := range flows.GetActions(flow) {
3083 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003085 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003088 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 }
Scott Baker355d1742019-10-24 10:57:52 -07003090 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003092 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003093 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003094 if out := action.GetPush(); out != nil {
3095 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003096 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 } else {
3098 actionInfo[PushVlan] = true
3099 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303101 log.Fields{
3102 "push-tpid": actionInfo[TPID].(uint32),
3103 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 }
3105 }
Scott Baker355d1742019-10-24 10:57:52 -07003106 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003107 if out := action.GetSetField(); out != nil {
3108 if field := out.GetField(); field != nil {
3109 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003110 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3113 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 }
3115 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003116 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003119 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003120 }
3121 }
3122 return nil
3123}
3124
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003126 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003127 fieldtype := ofbField.GetType()
3128 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003129 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3130 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003132 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003135 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3136 pcp := ofbField.GetVlanPcp()
3137 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003138 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003141 }
3142 }
3143}
3144
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003146 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003148 } else {
3149 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003151 }
3152}
3153
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003155 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003156 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003157 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3158 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003159 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003160 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303162 log.Fields{
3163 "newinport": classifierInfo[InPort].(uint32),
3164 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003165 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303166 return olterrors.NewErrNotFound("child-in-port",
3167 log.Fields{
3168 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3169 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003170 }
3171 }
3172 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003174 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003175 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003176 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003177 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303179 log.Fields{
3180 "newoutport": actionInfo[Output].(uint32),
3181 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003182 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303183 return olterrors.NewErrNotFound("out-port",
3184 log.Fields{
3185 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3186 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003187 }
3188 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3189 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003190 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003192 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303193 log.Fields{
3194 "newinport": actionInfo[Output].(uint32),
3195 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003196 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303197 return olterrors.NewErrNotFound("nni-port",
3198 log.Fields{
3199 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3200 "in-port": classifierInfo[InPort].(uint32),
3201 "out-port": actionInfo[Output].(uint32),
3202 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003203 }
3204 }
3205 }
3206 return nil
3207}
Gamze Abakafee36392019-10-03 11:17:24 +00003208
Neha Sharma96b7bf22020-06-15 10:37:32 +00003209func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003210 /* Metadata 8 bytes:
3211 Most Significant 2 Bytes = Inner VLAN
3212 Next 2 Bytes = Tech Profile ID(TPID)
3213 Least Significant 4 Bytes = Port ID
3214 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3215 subscriber related flows.
3216 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003217 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003218 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003219 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003220 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003222 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003223}
3224
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003225func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3226 for _, sliceElement := range slice {
3227 if sliceElement == item {
3228 return slice
3229 }
3230 }
3231 return append(slice, item)
3232}
3233
3234func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003235 for _, sliceElement := range slice {
3236 if sliceElement == item {
3237 return slice
3238 }
3239 }
3240 return append(slice, item)
3241}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303242
3243// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003244func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303245
3246 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3247 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003248 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003249 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003250 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003251 log.Fields{
3252 "port-number": action[Output].(uint32),
3253 "error": err})
3254 return uint32(0), err
3255 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303257 return intfID, nil
3258 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003259 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003260 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003262 log.Fields{
3263 "port-number": action[Output].(uint32),
3264 "error": err})
3265 return uint32(0), err
3266 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003267 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303268 return intfID, nil
3269 }
3270 return uint32(0), nil
3271}
3272
3273// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003274func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3275 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3276 if err != nil {
3277 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3278 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3279 return
3280 }
3281 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003282
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003283 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003284 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003285 f.packetInGemPortLock.RUnlock()
3286
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303287 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003288 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289 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 +05303290 log.Fields{
3291 "pktinkey": pktInkey,
3292 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003293 return
3294 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303295 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003296 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003297 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003298 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003299
npujarec5762e2020-01-01 14:08:48 +05303300 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003301 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 +05303302 log.Fields{
3303 "pktinkey": pktInkey,
3304 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303305}
3306
Esin Karaman7fb80c22020-07-16 14:23:33 +00003307//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3308func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3309 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003310 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003311 return 0, 0, errors.New("invalid packet length")
3312 }
3313 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3314 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3315
3316 var index int8
3317 if outerEthType == 0x8100 {
3318 if innerEthType == 0x8100 {
3319 // q-in-q 802.1ad or 802.1q double tagged packet.
3320 // get the inner vlanId
3321 index = 18
3322 } else {
3323 index = 14
3324 }
3325 priority := (packet[index] >> 5) & 0x7
3326 //13 bits composes vlanId value
3327 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3328 return vlan, priority, nil
3329 }
3330 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3331 return 0, 0, nil
3332}
3333
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303334// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303335func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003336
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003337 f.onuGemInfoLock.Lock()
3338 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003339
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003340 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303341 for idx, onu := range onugem {
3342 if onu.OnuID == onuID {
3343 for _, uni := range onu.UniPorts {
3344 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003345 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 +05303346 return
3347 }
3348 }
3349 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003350 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303351 }
3352 }
npujarec5762e2020-01-01 14:08:48 +05303353 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003354
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303355}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303356
npujarec5762e2020-01-01 14:08:48 +05303357func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3358 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303359 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003360 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303361 return
3362 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003363 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303364 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003365 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303366 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303368}
Esin Karamanccb714b2019-11-29 15:02:06 +00003369
Girish Gowdra9602eb42020-09-09 15:50:39 -07003370//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3371// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003372func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003373 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003374 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003375 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3376 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3377
Esin Karamanccb714b2019-11-29 15:02:06 +00003378 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003379 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 -07003380 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003381 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003382
3383 var onuID = int32(NoneOnuID)
3384 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003385 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3386 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3387 log.Fields{
3388 "flow": flow,
3389 "device-id": f.deviceHandler.device.Id,
3390 "intf-id": networkInterfaceID,
3391 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003392 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003393 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3394 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3395 log.Fields{
3396 "flow": flowInfo.Flow,
3397 "flow-id": flow.Id,
3398 "device-id": f.deviceHandler.device.Id})
3399 // Remove from device
3400 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3401 // DKB
3402 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3403 log.Fields{
3404 "flow-id": flow.Id,
3405 "error": err})
3406 return err
3407 }
3408 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003409 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003410}
3411
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003412// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3413func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3414 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3415 if err != nil {
3416 _ = olterrors.NewErrNotFound("onu", log.Fields{
3417 "pon-port": f.ponPortIdx}, err).Log()
3418 return
3419 }
3420
3421 f.subscriberDataPathFlowIDMapLock.Lock()
3422 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3423
3424 for _, onu := range onuGemInfo {
3425 for _, uniID := range onu.UniPorts {
3426 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3427 if err != nil {
3428 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3429 }
3430 for _, flowID := range flowIDs {
3431 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3432 if flowInfo == nil {
3433 // Error is already logged in the called function
3434 continue
3435 }
3436 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3437 flowInfo.Flow.FlowType == Downstream &&
3438 flowInfo.Flow.Classifier.OVid > 0 &&
3439 flowInfo.Flow.TechProfileId > 0 {
3440 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3441 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3442 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3443 }
3444 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3445 flowInfo.Flow.FlowType == Upstream &&
3446 flowInfo.Flow.Action.OVid > 0 &&
3447 flowInfo.Flow.TechProfileId > 0 {
3448 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3449 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3450 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3451 }
3452 }
3453 }
3454 }
3455 }
3456}
3457
3458// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3459func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3460 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3461}