blob: eb3592597daf3841a7baeccade13f309201812ad [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka01174422021-03-10 06:55:27 +000025 "github.com/opencord/voltha-lib-go/v4/pkg/meters"
Gamze Abaka7650be62021-02-26 10:50:36 +000026 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030027 "strings"
28 "sync"
29
Girish Gowdraa09aeab2020-09-14 16:30:52 -070030 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
31 "github.com/opencord/voltha-lib-go/v4/pkg/log"
32 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080033 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070034 "github.com/opencord/voltha-protos/v4/go/common"
35 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
36 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
37 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
38 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
39 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040040
Thomas Lee S94109f12020-03-03 16:39:29 +053041 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000042 "google.golang.org/grpc/codes"
43 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053044)
45
46const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070047 //IPProtoDhcp flow category
48 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053049
Girish Gowdraa09aeab2020-09-14 16:30:52 -070050 //IgmpProto proto value
51 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070052
53 //EapEthType eapethtype value
54 EapEthType = 0x888e
55 //LldpEthType lldp ethtype value
56 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000057 //IPv4EthType IPv4 ethernet type value
58 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030059 //PPPoEDEthType PPPoE discovery ethernet type value
60 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061
Andrea Campanella7acc0b92020-02-14 09:20:49 +010062 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
63 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040064
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065 //DefaultMgmtVlan default vlan value
66 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053067
manikkaraj kbf256be2019-03-25 00:13:48 +053068 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069
David K. Bainbridge82efc492019-09-04 09:57:11 -070070 //Upstream constant
71 Upstream = "upstream"
72 //Downstream constant
73 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000074 //Multicast constant
75 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //PacketTagType constant
77 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070078 //Untagged constant
79 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080 //SingleTag constant
81 SingleTag = "single_tag"
82 //DoubleTag constant
83 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053084
85 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086
87 //EthType constant
88 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000089 //EthDst constant
90 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091 //TPID constant
92 TPID = "tpid"
93 //IPProto constant
94 IPProto = "ip_proto"
95 //InPort constant
96 InPort = "in_port"
97 //VlanVid constant
98 VlanVid = "vlan_vid"
99 //VlanPcp constant
100 VlanPcp = "vlan_pcp"
101
102 //UDPDst constant
103 UDPDst = "udp_dst"
104 //UDPSrc constant
105 UDPSrc = "udp_src"
106 //Ipv4Dst constant
107 Ipv4Dst = "ipv4_dst"
108 //Ipv4Src constant
109 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Metadata constant
111 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 //TunnelID constant
113 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700114 //Output constant
115 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000116 //GroupID constant
117 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700118 // Actions
119
120 //PopVlan constant
121 PopVlan = "pop_vlan"
122 //PushVlan constant
123 PushVlan = "push_vlan"
124 //TrapToHost constant
125 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400126 //MaxMeterBand constant
127 MaxMeterBand = 2
128 //VlanPCPMask contant
129 VlanPCPMask = 0xFF
130 //VlanvIDMask constant
131 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000132 //IntfID constant
133 IntfID = "intfId"
134 //OnuID constant
135 OnuID = "onuId"
136 //UniID constant
137 UniID = "uniId"
138 //PortNo constant
139 PortNo = "portNo"
140 //AllocID constant
141 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000142 //GemID constant
143 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000144
145 //NoneOnuID constant
146 NoneOnuID = -1
147 //NoneUniID constant
148 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700149
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700150 // Max number of flows that can be queued per ONU
151 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530152
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700153 bitMapPrefix = "0b"
154 pbit1 = '1'
155)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400156
Esin Karamandf392e12020-12-16 13:33:09 +0000157type gemPortKey struct {
158 intfID uint32
159 gemPort uint32
160}
161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
163 direction tp_pb.Direction
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 tpID uint32
168 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700169 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000170 meterID uint32
171 flowMetadata *voltha.FlowMetadata
172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 portNo uint32
179 classifier map[string]interface{}
180 action map[string]interface{}
181 logicalFlow *ofp.OfpFlowStats
182 allocID uint32
183 gemPortID uint32
184 tpID uint32
185 pbitToGem map[uint32]uint32
186 gemToAes map[uint32]bool
187}
188
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700189// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
190type subscriberDataPathFlowIDKey struct {
191 intfID uint32
192 onuID uint32
193 uniID uint32
194 direction string
195 tpID uint32
196}
197
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700198// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
199// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
200// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
201// flow and processes it serially
202type flowControlBlock struct {
203 ctx context.Context // Flow handler context
204 addFlow bool // if true flow to be added, else removed
205 flow *voltha.OfpFlowStats // Flow message
206 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
207 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000208}
209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700210//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530211type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700212 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
213 techprofile map[uint32]tp.TechProfileIf
214 deviceHandler *DeviceHandler
215 grpMgr *OpenOltGroupMgr
216 resourceMgr *rsrcMgr.OpenOltResourceMgr
217
218 onuIdsLock sync.RWMutex // TODO: Do we need this?
219
220 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
221 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
222
223 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
224 packetInGemPortLock sync.RWMutex
225
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700226 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700227 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700228 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700229 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700231 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
232 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
233 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
234 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700235
236 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
237 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
238 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000239
240 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
241 gemToUniMap map[gemPortKey][]uint32
242 //We need to have a global lock on the gemToUniLock map
243 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530244}
245
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700246//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700247func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000248 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530249 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530250 var err error
251 var idx uint32
252
manikkaraj kbf256be2019-03-25 00:13:48 +0530253 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700254 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530255 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000256 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000257 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
258 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 return nil
260 }
William Kurkian740a09c2019-10-23 17:07:38 -0400261 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530263 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700265 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700266 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
267 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700268
269 // Create a slice of buffered channels for handling concurrent flows per ONU.
270 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
271 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
272 for i := range flowMgr.incomingFlows {
273 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
274 // Spin up a go routine to handling incoming flows (add/remove).
275 // There will be on go routine per ONU.
276 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
277 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
278 }
279
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530280 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700281 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
282 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 //Load flowID list per gem map per interface from the kvstore.
285 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000286 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000287
288 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
289 flowMgr.gemToUniLock = sync.RWMutex{}
290
Girish Gowdra9602eb42020-09-09 15:50:39 -0700291 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700292 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000293 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530294 return &flowMgr
295}
296
Esin Karamandf392e12020-12-16 13:33:09 +0000297// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
298func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
299 f.gemToUniLock.Lock()
300 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
301 f.gemToUniLock.Unlock()
302}
303
304// fromGemToUniMap returns onu and uni ID associated with the given key
305func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
306 f.gemToUniLock.RLock()
307 defer f.gemToUniLock.RUnlock()
308 val, ok := f.gemToUniMap[key]
309 return val, ok
310}
311
312// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
313func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
314 f.gemToUniLock.Lock()
315 defer f.gemToUniLock.Unlock()
316 delete(f.gemToUniMap, key)
317}
318
Kent Hagermane6ff1012020-07-14 15:07:53 -0400319func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700320 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
321 // Flow is not replicated in this case, we need to register the flow for a single gem-port
322 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
323 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
324 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
325 for _, gemPort := range deviceFlow.PbitToGemport {
326 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
327 return err
328 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700329 }
Gamze Abakafee36392019-10-03 11:17:24 +0000330 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700331 return nil
332}
333
334func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
335 f.flowsUsedByGemPortKey.Lock()
336 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
337 if !ok {
338 flowIDList = []uint64{flowFromCore.Id}
339 }
340 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
341 f.flowsUsedByGemPort[gemPortID] = flowIDList
342 f.flowsUsedByGemPortKey.Unlock()
343
344 // update the flowids for a gem to the KVstore
345 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400346}
347
Girish Gowdra9602eb42020-09-09 15:50:39 -0700348func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000349 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200350 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000351 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530352 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700353 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530354
Neha Sharma96b7bf22020-06-15 10:37:32 +0000355 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530356 "device-id": f.deviceHandler.device.Id,
357 "intf-id": intfID,
358 "onu-id": onuID,
359 "uni-id": uniID,
360 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700361 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530362 "action": actionInfo,
363 "usmeter-iD": UsMeterID,
364 "dsmeter-iD": DsMeterID,
365 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400366 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
367 // is because the flow is an NNI flow and there would be no onu resources associated with it
368 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400369 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200370 cause := "no-onu-id-for-flow"
371 fields := log.Fields{
372 "onu": onuID,
373 "port-no": portNo,
374 "classifer": classifierInfo,
375 "action": actionInfo,
376 "device-id": f.deviceHandler.device.Id}
377 logger.Errorw(ctx, cause, fields)
378 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530379 }
380
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700381 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000382 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530383 "uni": uni,
384 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530385
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700386 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
387 "device-id": f.deviceHandler.device.Id,
388 "intf-id": intfID,
389 "onu-id": onuID,
390 "uni-id": uniID,
391 "port-no": portNo,
392 "classifier": classifierInfo,
393 "action": actionInfo,
394 "usmeter-id": UsMeterID,
395 "dsmeter-id": DsMeterID,
396 "tp-id": TpID})
397 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
398 if allocID == 0 || gemPorts == nil || TpInst == nil {
399 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
400 return olterrors.NewErrNotFound(
401 "alloc-id-gem-ports-tp-unavailable",
402 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700404 args := make(map[string]uint32)
405 args[IntfID] = intfID
406 args[OnuID] = onuID
407 args[UniID] = uniID
408 args[PortNo] = portNo
409 args[AllocID] = allocID
410
411 /* Flows can be added specific to gemport if p-bits are received.
412 * If no pbit mentioned then adding flows for all gemports
413 */
414 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
415
Andrea Campanellabfe08432020-09-11 17:07:03 +0200416 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530417}
418
salmansiddiqui7ac62132019-08-22 03:58:50 +0000419// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530420func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400421
Neha Sharma96b7bf22020-06-15 10:37:32 +0000422 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530423 log.Fields{"dir": sq.direction,
424 "intf-id": sq.intfID,
425 "onu-id": sq.onuID,
426 "uni-id": sq.uniID,
427 "tp-id": sq.tpID,
428 "meter-id": sq.meterID,
429 "tp-inst": sq.tpInst,
430 "flowmetadata": sq.flowMetadata,
431 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432
Gamze Abakafee36392019-10-03 11:17:24 +0000433 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000434 if err != nil {
435 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
437
438 /* Lets make a simple assumption that if the meter-id is present on the KV store,
439 * then the scheduler and queues configuration is applied on the OLT device
440 * in the given direction.
441 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000442
Manikkaraj kb1d51442019-07-23 10:41:02 -0400443 var SchedCfg *tp_pb.SchedulerConfig
Girish Gowdraa482f272021-03-24 23:04:19 -0700444 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400445 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530446 return olterrors.NewErrNotFound("meter",
447 log.Fields{"intf-id": sq.intfID,
448 "onu-id": sq.onuID,
449 "uni-id": sq.uniID,
450 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000452
Girish Gowdraa482f272021-03-24 23:04:19 -0700453 if meterInfo != nil {
454 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id, "meter-id": sq.meterID})
455 if meterInfo.MeterConfig.MeterId == sq.meterID {
456 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
457 return err
458 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530461 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800462 "unsupported": "meter-id",
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 "kv-store-meter-id": meterInfo.MeterConfig.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "meter-id-in-flow": sq.meterID,
465 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000467
Neha Sharma96b7bf22020-06-15 10:37:32 +0000468 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530469 log.Fields{
470 "meter-id": sq.meterID,
471 "direction": Direction,
472 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000473
Gamze Abakafee36392019-10-03 11:17:24 +0000474 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000475 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000476 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000477 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000479
480 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530481 return olterrors.NewErrNotFound("scheduler-config",
482 log.Fields{
483 "intf-id": sq.intfID,
484 "direction": sq.direction,
485 "tp-inst": sq.tpInst,
486 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000487 }
488
Girish Gowdraa482f272021-03-24 23:04:19 -0700489 found := false
490 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000491 if sq.flowMetadata != nil {
492 for _, meter := range sq.flowMetadata.Meters {
493 if sq.meterID == meter.MeterId {
Girish Gowdraa482f272021-03-24 23:04:19 -0700494 meterInfo.MeterConfig = ofp.OfpMeterConfig{}
495 meterInfo.MeterConfig.MeterId = meter.MeterId
496 meterInfo.MeterConfig.Flags = meter.Flags
497 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
498 meterInfo.MeterConfig.Bands = append(meterInfo.MeterConfig.Bands, meter.Bands...)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000499 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdraa482f272021-03-24 23:04:19 -0700500 log.Fields{"meterConfig": meterInfo.MeterConfig,
Shrey Baid26912972020-04-16 21:02:31 +0530501 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700502 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 break
504 }
505 }
506 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000507 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400508 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700509 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530510 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800511 "reason": "Could-not-get-meterbands-from-flowMetadata",
512 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530513 "meter-id": sq.meterID,
514 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400515 }
Gamze Abaka01174422021-03-10 06:55:27 +0000516
517 var TrafficShaping *tp_pb.TrafficShapingInfo
518 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, &meterInfo.MeterConfig); err != nil {
519 return olterrors.NewErrInvalidValue(log.Fields{
520 "reason": "invalid-meter-config",
521 "meter-id": sq.meterID,
522 "device-id": f.deviceHandler.device.Id}, nil)
523 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400524
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700525 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000526 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700528 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530529 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
530 log.Fields{"intf-id": sq.intfID,
531 "direction": sq.direction,
532 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 }
534
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 * store the meter id on the KV store, for further reference.
537 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700538 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530539 return olterrors.NewErrAdapter("failed-updating-meter-id",
540 log.Fields{"onu-id": sq.onuID,
541 "meter-id": sq.meterID,
542 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530545 log.Fields{"direction": Direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700546 "meter-info": meterInfo,
547 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 return nil
549}
550
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700551func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000552 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
554 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530555 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
556 log.Fields{"intf-id": sq.intfID,
557 "direction": sq.direction,
558 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
560
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530562 log.Fields{
563 "direction": sq.direction,
564 "TrafficScheds": TrafficSched,
565 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530566 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000567 IntfId: sq.intfID, OnuId: sq.onuID,
568 UniId: sq.uniID, PortNo: sq.uniPort,
569 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000570 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530573 "direction": sq.direction,
574 "traffic-queues": trafficQueues,
575 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576
577 // On receiving the CreateTrafficQueues request, the driver should create corresponding
578 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530580 log.Fields{"direction": sq.direction,
581 "traffic-queues": trafficQueues,
582 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530583 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000584 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
585 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000586 TrafficQueues: trafficQueues,
587 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530588 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000590 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530591 "direction": sq.direction,
592 "traffic-queues": trafficQueues,
593 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000596 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000597 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700598 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000599 //assumed that there is only one queue per PON for the multicast service
600 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
601 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700604 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000605 gemPortID: multicastQueuePerPonPort.GemportId,
606 servicePriority: multicastQueuePerPonPort.Priority,
607 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700608 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000609 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400610 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
611 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
612 return err
613 }
Shrey Baid26912972020-04-16 21:02:31 +0530614
Neha Sharma96b7bf22020-06-15 10:37:32 +0000615 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000616 }
617 }
618 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 return nil
620}
621
salmansiddiqui7ac62132019-08-22 03:58:50 +0000622// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530623func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624
625 var Direction string
626 var SchedCfg *tp_pb.SchedulerConfig
627 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000628 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530629 log.Fields{
630 "direction": sq.direction,
631 "intf-id": sq.intfID,
632 "onu-id": sq.onuID,
633 "uni-id": sq.uniID,
634 "uni-port": sq.uniPort,
635 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000636 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000637 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400638 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000639 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000640 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 Direction = "downstream"
642 }
643
Girish Kumar8f73fe02019-12-09 13:19:37 +0000644 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530645 return olterrors.NewErrNotFound("scheduler-config",
646 log.Fields{
647 "int-id": sq.intfID,
648 "direction": sq.direction,
649 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000650 }
651
Girish Gowdraa482f272021-03-24 23:04:19 -0700652 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700654 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000655 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000656
Neha Sharma96b7bf22020-06-15 10:37:32 +0000657 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000658 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530659 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
660 log.Fields{
661 "intf-id": sq.intfID,
662 "direction": sq.direction,
663 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400665
npujarec5762e2020-01-01 14:08:48 +0530666 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000667 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
668 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000669 TrafficQueues: TrafficQueues,
670 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000671 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530672 log.Fields{
673 "intf-id": sq.intfID,
674 "traffic-queues": TrafficQueues,
675 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000677 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530678 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000679 IntfId: sq.intfID, OnuId: sq.onuID,
680 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400681 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000682 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530683 log.Fields{
684 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "traffic-schedulers": TrafficSched,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 }
690
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700691 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
692 log.Fields{"device-id": f.deviceHandler.device.Id,
693 "intf-id": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000697
698 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400699 * delete the meter id on the KV store.
700 */
Girish Gowdraa482f272021-03-24 23:04:19 -0700701 err = f.resourceMgr.RemoveMeterInfoForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530703 return olterrors.NewErrAdapter("unable-to-remove-meter",
704 log.Fields{
705 "onu": sq.onuID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700706 "device-id": f.deviceHandler.device.Id,
707 "intf-id": sq.intfID,
708 "onu-id": sq.onuID,
709 "uni-id": sq.uniID,
710 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000712 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530713 log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530714 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700715 "device-id": f.deviceHandler.device.Id,
716 "intf-id": sq.intfID,
717 "onu-id": sq.onuID,
718 "uni-id": sq.uniID,
719 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400720 return err
721}
722
Gamze Abakafee36392019-10-03 11:17:24 +0000723// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700724func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000725 var allocIDs []uint32
726 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530728 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000729 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000730
npujarec5762e2020-01-01 14:08:48 +0530731 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
732 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530734
Neha Sharma96b7bf22020-06-15 10:37:32 +0000735 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530736 "intf-id": intfID,
737 "onu-id": onuID,
738 "uni-id": uniID,
739 "device-id": f.deviceHandler.device.Id,
740 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530741
Manikkaraj kb1d51442019-07-23 10:41:02 -0400742 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530743 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000744 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000745 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530746 log.Fields{
747 "path": tpPath,
748 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530749 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000750 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530751 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000752 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530753 log.Fields{
754 "error": err,
755 "tp-id": TpID,
756 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000757 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530758 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400759 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
760 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
761 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530762 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000763 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530764 log.Fields{
765 "uni": uni,
766 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530767 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530768 }
Gamze Abakafee36392019-10-03 11:17:24 +0000769
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700770 switch tpInst := techProfileInstance.(type) {
771 case *tp.TechProfile:
772 if UsMeterID != 0 {
773 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
774 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
775 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000776 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700777 log.Fields{
778 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700779 "onu-id": onuID,
780 "uni-id": uniID,
781 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700782 "meter-id": UsMeterID,
783 "device-id": f.deviceHandler.device.Id})
784 return 0, nil, nil
785 }
786 }
787 if DsMeterID != 0 {
788 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
789 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
790 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000791 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700792 log.Fields{
793 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700794 "onu-id": onuID,
795 "uni-id": uniID,
796 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700797 "meter-id": DsMeterID,
798 "device-id": f.deviceHandler.device.Id})
799 return 0, nil, nil
800 }
801 }
802 allocID := tpInst.UsScheduler.AllocID
803 for _, gem := range tpInst.UpstreamGemPortAttributeList {
804 gemPortIDs = append(gemPortIDs, gem.GemportID)
805 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700806 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000807
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700808 if tpInstanceExists {
809 return allocID, gemPortIDs, techProfileInstance
810 }
811
812 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700813 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700814 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700816 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700817 "intf-id": intfID,
818 "onu-id": onuID,
819 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 "alloc-ids": allocIDs,
821 "gemports": allgemPortIDs,
822 "device-id": f.deviceHandler.device.Id})
823 // Send Tconts and GEM ports to KV store
824 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530825 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700826 case *tp.EponProfile:
827 // CreateSchedulerQueues for EPON needs to be implemented here
828 // when voltha-protos for EPON is completed.
829 allocID := tpInst.AllocID
830 for _, gem := range tpInst.UpstreamQueueAttributeList {
831 gemPortIDs = append(gemPortIDs, gem.GemportID)
832 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700833 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834
835 if tpInstanceExists {
836 return allocID, gemPortIDs, techProfileInstance
837 }
838
839 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700840 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 log.Fields{
844 "alloc-ids": allocIDs,
845 "gemports": allgemPortIDs,
846 "device-id": f.deviceHandler.device.Id})
847 // Send Tconts and GEM ports to KV store
848 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
849 return allocID, gemPortIDs, techProfileInstance
850 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 log.Fields{
853 "tpInst": tpInst})
854 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530855 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530856}
857
npujarec5762e2020-01-01 14:08:48 +0530858func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530859
Neha Sharma96b7bf22020-06-15 10:37:32 +0000860 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530861 log.Fields{
862 "intf-id": intfID,
863 "onu-id": onuID,
864 "uni-id": uniID,
865 "alloc-id": allocID,
866 "gemport-ids": gemPortIDs,
867 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530868 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530869 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530871 }
npujarec5762e2020-01-01 14:08:48 +0530872 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000873 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530874 }
npujarec5762e2020-01-01 14:08:48 +0530875 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamandf392e12020-12-16 13:33:09 +0000877 } else {
878 //add to gem to uni cache
879 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400882 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530883 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400884 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530885}
886
Esin Karamandf392e12020-12-16 13:33:09 +0000887//addGemPortUniAssociationsToCache
888func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
889 for _, gemPortID := range gemPortIDs {
890 key := gemPortKey{
891 intfID: intfID,
892 gemPort: gemPortID,
893 }
894 f.toGemToUniMap(ctx, key, onuID, uniID)
895 }
896 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
897 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
898}
899
Neha Sharma96b7bf22020-06-15 10:37:32 +0000900func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000901 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530902 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000903 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700904 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400905 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530907 log.Fields{
908 "intf-id": intfID,
909 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530910 }
911 }
912 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530914 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530915 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800916 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530917 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
918 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530919 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000920 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530921 log.Fields{
922 "numofTech": tpCount,
923 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
924 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530925 return nil
926}
927
Gamze Abaka7650be62021-02-26 10:50:36 +0000928func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
929 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000930 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530931 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000932 "uplinkClassifier": flowContext.classifier,
933 "uplinkAction": flowContext.action})
934 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530935 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530936}
937
Gamze Abaka7650be62021-02-26 10:50:36 +0000938func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
939 downlinkClassifier := flowContext.classifier
940 downlinkAction := flowContext.action
941
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700942 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530944 log.Fields{
945 "downlinkClassifier": downlinkClassifier,
946 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400947 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
948 if vlan, exists := downlinkClassifier[VlanVid]; exists {
949 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700950 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000951 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000954 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530955 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000956 "onu-id": flowContext.onuID,
957 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800958 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400959 }
960 }
961 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530962 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400963
Manikkaraj k884c1242019-04-11 16:26:42 +0530964 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400966 // vlan_vid is a uint32. must be type asserted as such or conversion fails
967 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530968 if ok {
969 downlinkAction[VlanVid] = dlClVid & 0xfff
970 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530971 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530972 "reason": "failed-to-convert-vlanid-classifier",
973 "vlan-id": VlanVid,
974 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530975 }
976
Gamze Abaka7650be62021-02-26 10:50:36 +0000977 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +0530978}
979
Gamze Abaka7650be62021-02-26 10:50:36 +0000980func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700981
982 var inverseDirection string
983 if direction == Upstream {
984 inverseDirection = Downstream
985 } else {
986 inverseDirection = Upstream
987 }
988
Gamze Abaka7650be62021-02-26 10:50:36 +0000989 intfID := flowContext.intfID
990 onuID := flowContext.onuID
991 uniID := flowContext.uniID
992 classifier := flowContext.classifier
993 action := flowContext.action
994 allocID := flowContext.allocID
995 gemPortID := flowContext.gemPortID
996 tpID := flowContext.tpID
997 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +0000998 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530999 log.Fields{
1000 "intf-id": intfID,
1001 "onu-id": onuID,
1002 "uni-id": uniID,
1003 "device-id": f.deviceHandler.device.Id,
1004 "classifier": classifier,
1005 "action": action,
1006 "direction": direction,
1007 "alloc-id": allocID,
1008 "gemport-id": gemPortID,
1009 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001010
1011 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001012 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301013 log.Fields{
1014 "device-id": f.deviceHandler.device.Id,
1015 "intf-id": intfID,
1016 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001017 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301018 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 classifierProto, err := makeOpenOltClassifierField(classifier)
1020 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301021 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301022 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301024 log.Fields{
1025 "classifier": *classifierProto,
1026 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001027 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001028 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301029 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301030 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001031 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301032 log.Fields{
1033 "action": *actionProto,
1034 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301036 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301037 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 log.Fields{
1039 "classifier": classifier,
1040 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301041 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301043 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001044
1045 // Get symmetric flowID if it exists
1046 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1047 // symmetric flow earlier
1048 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1049 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1050 f.subscriberDataPathFlowIDMapLock.RLock()
1051 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1052 f.subscriberDataPathFlowIDMapLock.RUnlock()
1053
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001054 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001055 OnuId: int32(onuID),
1056 UniId: int32(uniID),
1057 FlowId: logicalFlow.Id,
1058 FlowType: direction,
1059 AllocId: int32(allocID),
1060 NetworkIntfId: int32(networkIntfID),
1061 GemportId: int32(gemPortID),
1062 Classifier: classifierProto,
1063 Action: actionProto,
1064 Priority: int32(logicalFlow.Priority),
1065 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001066 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001067 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001068 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1069 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001070 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001071 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001072 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001074 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{"direction": direction,
1078 "device-id": f.deviceHandler.device.Id,
1079 "flow": flow,
1080 "intf-id": intfID,
1081 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001082 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1083 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1084 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "flow": flow,
1087 "device-id": f.deviceHandler.device.Id,
1088 "intf-id": intfID,
1089 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001091
1092 // Update the current flowID to the map
1093 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1094 f.subscriberDataPathFlowIDMapLock.Lock()
1095 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1096 f.subscriberDataPathFlowIDMapLock.Unlock()
1097
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301099}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001100
Gamze Abaka7650be62021-02-26 10:50:36 +00001101func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1102
1103 intfID := flowContext.intfID
1104 onuID := flowContext.onuID
1105 uniID := flowContext.uniID
1106 logicalFlow := flowContext.logicalFlow
1107 classifier := flowContext.classifier
1108 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301109
Neha Sharma96b7bf22020-06-15 10:37:32 +00001110 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301111 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301112 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301114 "action": action,
1115 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301117 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301118
1119 // Clear the action map
1120 for k := range action {
1121 delete(action, k)
1122 }
1123
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001124 action[TrapToHost] = true
1125 classifier[UDPSrc] = uint32(68)
1126 classifier[UDPDst] = uint32(67)
1127 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301128
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001129 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001130 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301131 log.Fields{
1132 "device-id": f.deviceHandler.device.Id,
1133 "intf-id": intfID,
1134 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001135 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301136 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301139 log.Fields{
1140 "ul_classifier": classifier,
1141 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001142 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301143 "intf-id": intfID,
1144 "onu-id": onuID,
1145 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
David K. Bainbridge794735f2020-02-11 21:01:37 -08001147 classifierProto, err := makeOpenOltClassifierField(classifier)
1148 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301149 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001152 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301154 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301155 }
1156
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001158 OnuId: int32(onuID),
1159 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001160 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001161 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001162 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001163 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001164 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301165 Classifier: classifierProto,
1166 Action: actionProto,
1167 Priority: int32(logicalFlow.Priority),
1168 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001169 PortNo: flowContext.portNo,
1170 TechProfileId: flowContext.tpID,
1171 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1172 PbitToGemport: flowContext.pbitToGem,
1173 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001174 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001176 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001177 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301179 log.Fields{
1180 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001181 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301182 "intf-id": intfID,
1183 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001184 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1185 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(dhcpFlow.AccessIntfId), dhcpFlow.OnuId, dhcpFlow.UniId, dhcpFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301186 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1187 log.Fields{
1188 "flow": dhcpFlow,
1189 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301190 }
1191
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301193}
1194
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001196func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1197 delete(flowContext.classifier, VlanVid)
1198 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001199}
1200
1201//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001202func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1203
1204 intfID := flowContext.intfID
1205 onuID := flowContext.onuID
1206 uniID := flowContext.uniID
1207 logicalFlow := flowContext.logicalFlow
1208 classifier := flowContext.classifier
1209 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001210
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001212 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301213 return olterrors.NewErrNotFound("nni-interface-id",
1214 log.Fields{
1215 "classifier": classifier,
1216 "action": action,
1217 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001219 }
1220
1221 // Clear the action map
1222 for k := range action {
1223 delete(action, k)
1224 }
1225
1226 action[TrapToHost] = true
1227 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001228
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001229 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001230 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001231 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232 }
1233
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301235 log.Fields{
1236 "ul_classifier": classifier,
1237 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001238 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301239 "device-id": f.deviceHandler.device.Id,
1240 "intf-id": intfID,
1241 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 classifierProto, err := makeOpenOltClassifierField(classifier)
1244 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301245 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001246 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301248 log.Fields{
1249 "classifier": *classifierProto,
1250 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001251 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301253 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 }
1255
David K. Bainbridge794735f2020-02-11 21:01:37 -08001256 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257 OnuId: int32(onuID),
1258 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001259 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001260 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001261 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001263 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264 Classifier: classifierProto,
1265 Action: actionProto,
1266 Priority: int32(logicalFlow.Priority),
1267 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001268 PortNo: flowContext.portNo,
1269 TechProfileId: flowContext.tpID,
1270 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1271 PbitToGemport: flowContext.pbitToGem,
1272 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001273 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001274
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001276 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001277 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001278
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001279 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1280 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301281 return olterrors.NewErrPersistence("update", "flow", flow.FlowId, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282 }
1283
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285}
1286
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001287// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001288func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1289 intfID := flowContext.intfID
1290 onuID := flowContext.onuID
1291 uniID := flowContext.uniID
1292 portNo := flowContext.portNo
1293 allocID := flowContext.allocID
1294 gemPortID := flowContext.gemPortID
1295 logicalFlow := flowContext.logicalFlow
1296 classifier := flowContext.classifier
1297 action := flowContext.action
1298
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001299 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301300 log.Fields{
1301 "intf-id": intfID,
1302 "onu-id": onuID,
1303 "port-no": portNo,
1304 "alloc-id": allocID,
1305 "gemport-id": gemPortID,
1306 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001307 "flow": logicalFlow,
1308 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301309
1310 uplinkClassifier := make(map[string]interface{})
1311 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301312
manikkaraj kbf256be2019-03-25 00:13:48 +05301313 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001314 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001315 uplinkClassifier[PacketTagType] = SingleTag
1316 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001317 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301318 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001319 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001321 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301322 "device-id": f.deviceHandler.device.Id,
1323 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001324 "intf-id": intfID,
1325 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301327 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001328 //Add Uplink EthType Flow
1329 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301330 log.Fields{
1331 "ul_classifier": uplinkClassifier,
1332 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001333 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301334 "device-id": f.deviceHandler.device.Id,
1335 "intf-id": intfID,
1336 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1339 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301340 return olterrors.NewErrInvalidValue(log.Fields{
1341 "classifier": uplinkClassifier,
1342 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301345 log.Fields{
1346 "classifier": *classifierProto,
1347 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001348 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301350 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001352 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "action": *actionProto,
1355 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001356 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301357 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301358 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001359 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301360 "action": action,
1361 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301363 }
1364
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001366 OnuId: int32(onuID),
1367 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001368 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001369 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 AllocId: int32(allocID),
1371 NetworkIntfId: int32(networkIntfID),
1372 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 Classifier: classifierProto,
1374 Action: actionProto,
1375 Priority: int32(logicalFlow.Priority),
1376 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001377 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001378 TechProfileId: flowContext.tpID,
1379 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1380 PbitToGemport: flowContext.pbitToGem,
1381 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001382 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001384 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001386 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301387 log.Fields{
1388 "device-id": f.deviceHandler.device.Id,
1389 "onu-id": onuID,
1390 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001391 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301392 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001393 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1394 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(upstreamFlow.AccessIntfId), upstreamFlow.OnuId, upstreamFlow.UniId, upstreamFlow.FlowId, flowInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301395 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1396 log.Fields{
1397 "flow": upstreamFlow,
1398 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301399 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301401}
1402
David K. Bainbridge794735f2020-02-11 21:01:37 -08001403func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001405
1406 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1407 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1408 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001409 if vlanID != ReservedVlan {
1410 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001411 classifier.OVid = vid
1412 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001414 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1415 vid := uint32(metadata)
1416 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001417 classifier.IVid = vid
1418 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301419 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301420 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001421 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301422 classifier.OPbits = vlanPcp
1423 } else {
1424 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301425 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001426 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1427 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1428 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1429 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001430 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1432 classifier.PktTagType = pktTagType
1433
1434 switch pktTagType {
1435 case SingleTag:
1436 case DoubleTag:
1437 case Untagged:
1438 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001439 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301440 }
1441 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001442 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301443}
1444
Gamze Abaka724d0852020-03-18 12:10:24 +00001445func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 var actionCmd openoltpb2.ActionCmd
1447 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001449 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001451 if _, ok := actionInfo[VlanPcp]; ok {
1452 action.Cmd.RemarkInnerPbits = true
1453 action.IPbits = actionInfo[VlanPcp].(uint32)
1454 if _, ok := actionInfo[VlanVid]; ok {
1455 action.Cmd.TranslateInnerTag = true
1456 action.IVid = actionInfo[VlanVid].(uint32)
1457 }
1458 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 } else if _, ok := actionInfo[PushVlan]; ok {
1460 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001462 if _, ok := actionInfo[VlanPcp]; ok {
1463 action.OPbits = actionInfo[VlanPcp].(uint32)
1464 action.Cmd.RemarkOuterPbits = true
1465 if _, ok := classifierInfo[VlanVid]; ok {
1466 action.IVid = classifierInfo[VlanVid].(uint32)
1467 action.Cmd.TranslateInnerTag = true
1468 }
1469 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001470 } else if _, ok := actionInfo[TrapToHost]; ok {
1471 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301472 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001473 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001475 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301476}
1477
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001478// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001479func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1480 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301481}
1482
Gamze Abakafee36392019-10-03 11:17:24 +00001483// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001484func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301485 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001486 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1487
Gamze Abakafee36392019-10-03 11:17:24 +00001488 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301489 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001490 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301491 // return err
1492 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001493 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001494 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001495 }
1496 return nil
1497}
1498
1499// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301500func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001501 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001502 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001503 }
npujarec5762e2020-01-01 14:08:48 +05301504 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301505 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1506 log.Fields{
1507 "tp-id": tpID,
1508 "uni-port-name": uniPortName,
1509 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001510 }
1511 return nil
1512}
1513
David K. Bainbridge794735f2020-02-11 21:01:37 -08001514func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001515
1516 var intfID uint32
1517 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1518 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1519 */
1520 if deviceFlow.AccessIntfId != -1 {
1521 intfID = uint32(deviceFlow.AccessIntfId)
1522 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001523 // We need to log the valid interface ID.
1524 // For trap-on-nni flows, the access_intf_id is invalid (-1), so choose the network_intf_id.
Daniele Rossi22db98e2019-07-11 11:50:00 +00001525 intfID = uint32(deviceFlow.NetworkIntfId)
1526 }
1527
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301529 "flow": *deviceFlow,
1530 "device-id": f.deviceHandler.device.Id,
1531 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001532 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001533
1534 st, _ := status.FromError(err)
1535 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001536 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001537 "err": err,
1538 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301539 "device-id": f.deviceHandler.device.Id,
1540 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001541 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301542 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001543
1544 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301546 log.Fields{"err": err,
1547 "device-flow": deviceFlow,
1548 "device-id": f.deviceHandler.device.Id,
1549 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001552 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301553 log.Fields{
1554 "flow": *deviceFlow,
1555 "device-id": f.deviceHandler.device.Id,
1556 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001557
1558 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1559 if deviceFlow.AccessIntfId != -1 {
1560 // No need to register the flow if it is a trap on nni flow.
1561 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1562 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1563 return err
1564 }
1565 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001567}
1568
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1570 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301571 log.Fields{
1572 "flow": *deviceFlow,
1573 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001574 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001575 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001576 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301578 log.Fields{
1579 "err": err,
1580 "deviceFlow": deviceFlow,
1581 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001582 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001584 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001585 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001586
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001587 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001588 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001589 "of-flow-id": ofFlowID,
1590 "flow": *deviceFlow,
1591 "device-id": f.deviceHandler.device.Id,
1592 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001593 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301594}
1595
David K. Bainbridge794735f2020-02-11 21:01:37 -08001596func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001597
1598 classifierInfo := make(map[string]interface{})
1599 actionInfo := make(map[string]interface{})
1600
1601 classifierInfo[EthType] = uint32(LldpEthType)
1602 classifierInfo[PacketTagType] = Untagged
1603 actionInfo[TrapToHost] = true
1604
1605 // LLDP flow is installed to trap LLDP packets on the NNI port.
1606 // We manage flow_id resource pool on per PON port basis.
1607 // Since this situation is tricky, as a hack, we pass the NNI port
1608 // index (network_intf_id) as PON port Index for the flow_id resource
1609 // pool. Also, there is no ONU Id available for trapping LLDP packets
1610 // on NNI port, use onu_id as -1 (invalid)
1611 // ****************** CAVEAT *******************
1612 // This logic works if the NNI Port Id falls within the same valid
1613 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1614 // we need to have a re-look at this.
1615 // *********************************************
1616
1617 var onuID = -1
1618 var uniID = -1
1619 var gemPortID = -1
1620
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001622 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301623 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001624 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001625 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001628 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001629
David K. Bainbridge794735f2020-02-11 21:01:37 -08001630 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1631 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301632 return olterrors.NewErrInvalidValue(
1633 log.Fields{
1634 "classifier": classifierInfo,
1635 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001636 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001637 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301638 log.Fields{
1639 "classifier": *classifierProto,
1640 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001641 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001642 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301643 return olterrors.NewErrInvalidValue(
1644 log.Fields{
1645 "action": actionInfo,
1646 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "action": *actionProto,
1651 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001652
1653 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1654 OnuId: int32(onuID), // OnuId not required
1655 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001656 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001657 FlowType: Downstream,
1658 NetworkIntfId: int32(networkInterfaceID),
1659 GemportId: int32(gemPortID),
1660 Classifier: classifierProto,
1661 Action: actionProto,
1662 Priority: int32(flow.Priority),
1663 Cookie: flow.Cookie,
1664 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001666 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301667 log.Fields{
1668 "flow": downstreamflow,
1669 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "device-id": f.deviceHandler.device.Id,
1674 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675 "flow-id": flow.Id})
1676 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1677 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1678 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301679 log.Fields{
1680 "flow": downstreamflow,
1681 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 }
1683 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301684}
1685
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001686func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1687 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001688}
1689
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001690//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001692 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1693 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1694 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001695 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301696 log.Fields{
1697 "intf-id": intfID,
1698 "onu-id": onuID,
1699 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001700 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001701 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301702 return nil, olterrors.NewErrNotFound("onu-child-device",
1703 log.Fields{
1704 "onu-id": onuID,
1705 "intf-id": intfID,
1706 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001707 }
1708 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1709 //better to ad the device to cache here.
1710 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1711 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301713 log.Fields{
1714 "intf-id": intfID,
1715 "onu-id": onuID,
1716 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001717 }
1718
1719 return onuDev.(*OnuDevice), nil
1720}
1721
1722//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1724 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "pon-port": intfID,
1727 "onu-id": onuID,
1728 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001729 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001731 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301732 return nil, olterrors.NewErrNotFound("onu",
1733 log.Fields{
1734 "interface-id": parentPortNo,
1735 "onu-id": onuID,
1736 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001737 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301738 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301740 log.Fields{
1741 "device-id": f.deviceHandler.device.Id,
1742 "child_device_id": onuDevice.Id,
1743 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301744 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301745}
1746
Neha Sharma96b7bf22020-06-15 10:37:32 +00001747func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1748 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301749 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001750 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301751 log.Fields{
1752 "intf-id": intfID,
1753 "onu-id": onuID,
1754 "uni-id": uniID,
1755 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001756 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301757 }
1758
1759 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "msg": *delGemPortMsg,
1763 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001764 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301765 delGemPortMsg,
1766 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001767 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001768 onuDev.deviceType,
1769 onuDev.deviceID,
1770 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301771 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1772 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001773 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301774 "to-adapter": onuDev.deviceType,
1775 "onu-id": onuDev.deviceID,
1776 "proxyDeviceID": onuDev.proxyDeviceID,
1777 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301778 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "msg": delGemPortMsg,
1782 "from-adapter": f.deviceHandler.device.Type,
1783 "to-adapter": onuDev.deviceType,
1784 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301785 return nil
1786}
1787
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1789 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301790 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301792 log.Fields{
1793 "intf-id": intfID,
1794 "onu-id": onuID,
1795 "uni-id": uniID,
1796 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001797 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301798 }
1799
1800 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001801 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301802 log.Fields{
1803 "msg": *delTcontMsg,
1804 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001805 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301806 delTcontMsg,
1807 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001808 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001809 onuDev.deviceType,
1810 onuDev.deviceID,
1811 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301812 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1813 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001814 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301815 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1816 "proxyDeviceID": onuDev.proxyDeviceID,
1817 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301818 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001819 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301820 log.Fields{
1821 "msg": delTcontMsg,
1822 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301823 return nil
1824}
1825
Girish Gowdrac3037402020-01-22 20:29:53 +05301826// Once the gemport is released for a given onu, it also has to be cleared from local cache
1827// which was used for deriving the gemport->logicalPortNo during packet-in.
1828// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1829// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001831
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001832 f.onuGemInfoLock.Lock()
1833 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001834
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001837 "gem-port-id": gemPortID,
1838 "intf-id": intfID,
1839 "onu-id": onuID,
1840 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001841 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001842
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001843 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001844deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001845 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301846 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001847 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301848 // If the gemport is found, delete it from local cache.
1849 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001850 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1851 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301853 log.Fields{
1854 "intf-id": intfID,
1855 "onu-id": onuID,
1856 "deletedgemport-id": gemPortID,
1857 "gemports": onu.GemPorts,
1858 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001859 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301860 }
1861 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001862 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301863 }
1864 }
1865}
1866
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301867//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001868// nolint: gocyclo
Girish Gowdraa482f272021-03-24 23:04:19 -07001869func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, intfID uint32, onuID int32, uniID int32,
Girish Gowdra82c80982021-03-26 16:22:02 -07001870 gemPortID int32, flowID uint64, portNum uint32, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001871
Girish Gowdraa482f272021-03-24 23:04:19 -07001872 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1873 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001874 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1875 log.Fields{
1876 "tpPath": tpPath,
1877 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001878 techprofileInst, err := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001879 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1880 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1881 log.Fields{
1882 "tp-id": tpID,
1883 "path": tpPath}, err)
1884 }
1885
1886 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1887
1888 if used {
1889 f.flowsUsedByGemPortKey.Lock()
1890 defer f.flowsUsedByGemPortKey.Unlock()
1891
1892 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1893 for i, flowIDinMap := range flowIDs {
1894 if flowIDinMap == flowID {
1895 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1896 // everytime flowsUsedByGemPort cache is updated the same should be updated
1897 // in kv store by calling UpdateFlowIDsForGem
1898 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
Girish Gowdraa482f272021-03-24 23:04:19 -07001899 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, uint32(gemPortID), flowIDs); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001900 return err
1901 }
1902 break
1903 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001904 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001905 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1906 log.Fields{
1907 "gemport-id": gemPortID,
1908 "usedByFlows": flowIDs,
1909 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -07001910
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001911 return nil
1912 }
1913 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
Girish Gowdraa482f272021-03-24 23:04:19 -07001914 f.resourceMgr.RemoveGemPortIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1916 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
Girish Gowdraa482f272021-03-24 23:04:19 -07001917 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), intfID)
Esin Karamandf392e12020-12-16 13:33:09 +00001918 // also clear gem to uni cache
1919 f.removeFromGemToUniMap(gemPortKey{
Girish Gowdraa482f272021-03-24 23:04:19 -07001920 intfID: intfID,
Esin Karamandf392e12020-12-16 13:33:09 +00001921 gemPort: uint32(gemPortID),
1922 })
Girish Gowdraa482f272021-03-24 23:04:19 -07001923 f.deleteGemPortFromLocalCache(ctx, intfID, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001924
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 f.onuIdsLock.Lock() // TODO: What is this lock?
1926
1927 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1928 // by calling DeleteFlowIDsForGem
1929 f.flowsUsedByGemPortKey.Lock()
1930 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1931 f.flowsUsedByGemPortKey.Unlock()
Girish Gowdraa482f272021-03-24 23:04:19 -07001932 f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, uint32(gemPortID))
1933 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001934
1935 f.onuIdsLock.Unlock()
1936
1937 // Delete the gem port on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001938 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1940 log.Fields{
1941 "err": err,
Girish Gowdraa482f272021-03-24 23:04:19 -07001942 "intfID": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943 "onu-id": onuID,
1944 "uni-id": uniID,
1945 "device-id": f.deviceHandler.device.Id,
1946 "gemport-id": gemPortID})
1947 }
1948 switch techprofileInst := techprofileInst.(type) {
1949 case *tp.TechProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001950 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, intfID, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001951 if !ok {
Girish Gowdraa482f272021-03-24 23:04:19 -07001952 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953 logger.Warn(ctx, err)
1954 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001955 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001956 logger.Warn(ctx, err)
1957 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001958 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001959 logger.Warn(ctx, err)
1960 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001961 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 logger.Warn(ctx, err)
1963 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001964 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001965 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001966 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001967 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1968 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001969 "intf": intfID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001970 "onu-id": onuID,
1971 "uni-id": uniID,
1972 "device-id": f.deviceHandler.device.Id,
1973 "alloc-id": techprofileInst.UsScheduler.AllocID})
1974 }
1975 }
1976 case *tp.EponProfile:
Girish Gowdraa482f272021-03-24 23:04:19 -07001977 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 logger.Warn(ctx, err)
1979 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001980 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 logger.Warn(ctx, err)
1982 }
Girish Gowdraa482f272021-03-24 23:04:19 -07001983 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001984 // Delete the TCONT on the ONU.
Girish Gowdraa482f272021-03-24 23:04:19 -07001985 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301987 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07001988 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05301989 "onu-id": onuID,
1990 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001991 "device-id": f.deviceHandler.device.Id,
1992 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001993 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001994 default:
1995 logger.Errorw(ctx, "error-unknown-tech",
1996 log.Fields{
1997 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001998 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001999
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302000 return nil
2001}
2002
David K. Bainbridge794735f2020-02-11 21:01:37 -08002003// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002004func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002005 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302007 log.Fields{
2008 "flowDirection": flowDirection,
2009 "flow": *flow,
2010 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002011
2012 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002013 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002014 }
2015
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302016 classifierInfo := make(map[string]interface{})
2017
Neha Sharma96b7bf22020-06-15 10:37:32 +00002018 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002020 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002021 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302022 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302023
David K. Bainbridge794735f2020-02-11 21:01:37 -08002024 onuID := int32(onu)
2025 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302026
2027 for _, field := range flows.GetOfbFields(flow) {
2028 if field.Type == flows.IP_PROTO {
2029 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002030 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302031 }
2032 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002033 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302034 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002035 "flow-id": flow.Id,
2036 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302037 "onu-id": onuID,
2038 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302039
2040 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2041 onuID = -1
2042 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002043 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2044 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002045 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002046 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002047 log.Fields{
2048 "port-number": inPort,
2049 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002050 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002051 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002053 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2054 logger.Errorw(ctx, "flow-info-not-found-for-flow-to-be-removed", log.Fields{"flow-id": flow.Id, "intf-id": Intf, "onu-id": onuID, "uni-id": uniID})
2055 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2056 }
2057 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2058 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2059 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2060 return err
2061 }
2062 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2063 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2064 return err
2065 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002066 tpID, err := getTpIDFromFlow(ctx, flow)
2067 if err != nil {
2068 return olterrors.NewErrNotFound("tp-id",
2069 log.Fields{
2070 "flow": flow,
2071 "intf-id": Intf,
2072 "onu-id": onuID,
2073 "uni-id": uniID,
2074 "device-id": f.deviceHandler.device.Id}, err)
2075 }
2076
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002077 if !flowInfo.Flow.ReplicateFlow {
Girish Gowdra82c80982021-03-26 16:22:02 -07002078 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002079 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002080 "flow-id": flow.Id,
2081 "stored-flow": flowInfo.Flow,
2082 "device-id": f.deviceHandler.device.Id,
2083 "stored-flow-id": flowInfo.Flow.FlowId,
2084 "onu-id": onuID,
2085 "intf": Intf,
Girish Gowdra82c80982021-03-26 16:22:02 -07002086 "err": err,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002087 })
2088 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302089 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002090 } else {
2091 gems := make([]uint32, 0)
2092 for _, gem := range flowInfo.Flow.PbitToGemport {
2093 gems = appendUnique32bit(gems, gem)
2094 }
2095 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2096 for _, gem := range gems {
Girish Gowdra82c80982021-03-26 16:22:02 -07002097 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum, tpID); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002098 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002099 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002101 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002102 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002103 "onu-id": onuID,
2104 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002105 "gem": gem,
Girish Gowdra82c80982021-03-26 16:22:02 -07002106 "err": err,
Matteo Scandolo92186242020-06-12 10:54:18 -07002107 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002108 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302109 }
2110 }
2111 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002112
2113 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2114 if isDatapathFlow(flow) {
2115 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2116 var inverseDirection string
2117 if flowDirection == Upstream {
2118 inverseDirection = Downstream
2119 } else {
2120 inverseDirection = Upstream
2121 }
2122
2123 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002124 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002125 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002126 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002127 }
2128 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002129 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2130 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2131 return err
2132 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002133 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002134}
2135
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002136//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002137func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002138
Neha Sharma96b7bf22020-06-15 10:37:32 +00002139 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302140 var direction string
2141 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002142
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302143 for _, action := range flows.GetActions(flow) {
2144 if action.Type == flows.OUTPUT {
2145 if out := action.GetOutput(); out != nil {
2146 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002147 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302148 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002149 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002150 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002151 }
2152 }
2153 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002154
2155 if flows.HasGroup(flow) {
2156 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002157 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002158 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302159 direction = Upstream
2160 } else {
2161 direction = Downstream
2162 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302163
Girish Gowdracefae192020-03-19 18:14:10 -07002164 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002165 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002166
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002167 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002168}
2169
Esin Karamanae41e2b2019-12-17 18:13:13 +00002170//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2171func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2172 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2173 if ethType, ok := classifierInfo[EthType]; ok {
2174 if ethType.(uint32) == IPv4EthType {
2175 if ipProto, ok := classifierInfo[IPProto]; ok {
2176 if ipProto.(uint32) == IgmpProto {
2177 return true
2178 }
2179 }
2180 }
2181 }
2182 }
2183 return false
2184}
2185
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002186// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2187func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2188 // Step1 : Fill flowControlBlock
2189 // Step2 : Push the flowControlBlock to ONU channel
2190 // Step3 : Wait on response channel for response
2191 // Step4 : Return error value
2192 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2193 errChan := make(chan error)
2194 flowCb := flowControlBlock{
2195 ctx: ctx,
2196 addFlow: addFlow,
2197 flow: flow,
2198 flowMetadata: flowMetadata,
2199 errChan: &errChan,
2200 }
2201 inPort, outPort := getPorts(flow)
2202 var onuID uint32
2203 if inPort != InvalidPort && outPort != InvalidPort {
2204 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2205 }
2206 // inPort or outPort is InvalidPort for trap-from-nni flows.
2207 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2208 // Send the flowCb on the ONU flow channel
2209 f.incomingFlows[onuID] <- flowCb
2210 // Wait on the channel for flow handlers return value
2211 err := <-errChan
2212 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2213 return err
2214}
2215
2216// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2217// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2218func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2219 for {
2220 // block on the channel to receive an incoming flow
2221 // process the flow completely before proceeding to handle the next flow
2222 flowCb := <-subscriberFlowChannel
2223 if flowCb.addFlow {
2224 logger.Debugw(flowCb.ctx, "adding-flow",
2225 log.Fields{"device-id": f.deviceHandler.device.Id,
2226 "flowToAdd": flowCb.flow})
2227 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2228 // Pass the return value over the return channel
2229 *flowCb.errChan <- err
2230 } else {
2231 logger.Debugw(flowCb.ctx, "removing-flow",
2232 log.Fields{"device-id": f.deviceHandler.device.Id,
2233 "flowToRemove": flowCb.flow})
2234 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2235 // Pass the return value over the return channel
2236 *flowCb.errChan <- err
2237 }
2238 }
2239}
2240
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002241// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302242// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002243func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002244 classifierInfo := make(map[string]interface{})
2245 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002246 var UsMeterID uint32
2247 var DsMeterID uint32
2248
Neha Sharma96b7bf22020-06-15 10:37:32 +00002249 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302250 log.Fields{
2251 "flow": flow,
2252 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002254
Neha Sharma96b7bf22020-06-15 10:37:32 +00002255 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002256 if err != nil {
2257 // Error logging is already done in the called function
2258 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302260 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002261
Esin Karamanccb714b2019-11-29 15:02:06 +00002262 if flows.HasGroup(flow) {
2263 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002264 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002265 }
2266
manikkaraj k17652a72019-05-06 09:06:36 -04002267 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002269 if err != nil {
2270 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002271 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002272 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002273
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302275 log.Fields{
2276 "classifierinfo_inport": classifierInfo[InPort],
2277 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002278 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002279
Humera Kouser94d7a842019-08-25 19:04:32 -04002280 if ethType, ok := classifierInfo[EthType]; ok {
2281 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002282 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002283 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002284 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002285 if ethType.(uint32) == PPPoEDEthType {
2286 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2287 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2288 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2289 }
2290 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002291 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002292 if ipProto, ok := classifierInfo[IPProto]; ok {
2293 if ipProto.(uint32) == IPProtoDhcp {
2294 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302295 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002296 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002297 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002298 }
2299 }
2300 }
2301 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002302 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002304 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002305 }
A R Karthick1f85b802019-10-11 05:06:05 +00002306
npujarec5762e2020-01-01 14:08:48 +05302307 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002308
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002310 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302311 return olterrors.NewErrNotFound("tpid-for-flow",
2312 log.Fields{
2313 "flow": flow,
2314 "intf-id": IntfID,
2315 "onu-id": onuID,
2316 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002317 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302319 log.Fields{
2320 "tp-id": TpID,
2321 "intf-id": intfID,
2322 "onu-id": onuID,
2323 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002324 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002325 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002327 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002328 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002330
2331 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002332 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002333}
Girish Gowdra3d633032019-12-10 16:37:05 +05302334
Esin Karamanccb714b2019-11-29 15:02:06 +00002335// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002336func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002337 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302339 "classifier-info": classifierInfo,
2340 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002341
Esin Karaman65409d82020-03-18 10:58:18 +00002342 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002343 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002344 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002345 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002346
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002347 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002348
David K. Bainbridge794735f2020-02-11 21:01:37 -08002349 onuID := NoneOnuID
2350 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002351
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002352 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002354 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002356 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2357 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002358 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002359 }
2360 groupID := actionInfo[GroupID].(uint32)
2361 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002362 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002363 FlowType: Multicast,
2364 NetworkIntfId: int32(networkInterfaceID),
2365 GroupId: groupID,
2366 Classifier: classifierProto,
2367 Priority: int32(flow.Priority),
2368 Cookie: flow.Cookie}
2369
Kent Hagermane6ff1012020-07-14 15:07:53 -04002370 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002371 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002372 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002374 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002375 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002376 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002377 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002378 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002379 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002380 //cached group can be removed now
2381 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2382 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2383 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002384 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002385
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002386 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2387 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2388 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002389 }
2390 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002391}
2392
Esin Karaman65409d82020-03-18 10:58:18 +00002393//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2394func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2395 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002396 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002397 if err != nil {
2398 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2399 }
2400 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002401 }
Esin Karaman65409d82020-03-18 10:58:18 +00002402 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302403 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002404 if e == nil && len(nniPorts) > 0 {
2405 return nniPorts[0], nil
2406 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302407 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002408}
2409
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002410//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002411func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002412
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302414 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302416 log.Fields{
2417 "intf-id": intfID,
2418 "onu-id": onuID,
2419 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002420 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302421 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002422 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002423
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002425 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002426 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002427 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002428 tpDownloadMsg,
2429 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002430 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002431 onuDev.deviceType,
2432 onuDev.deviceID,
2433 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002434 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302435 return olterrors.NewErrCommunication("send-techprofile-download-request",
2436 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002437 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302438 "to-adapter": onuDev.deviceType,
2439 "onu-id": onuDev.deviceID,
2440 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302443 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302444}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002445
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302446//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002447func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302448
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002449 f.onuGemInfoLock.Lock()
2450 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002451 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002452 // If the ONU already exists in onuGemInfo list, nothing to do
2453 for _, onu := range onugem {
2454 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2455 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2456 log.Fields{"onuID": onuID,
2457 "serialNum": serialNum})
2458 return nil
2459 }
2460 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002461
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302462 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002463 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002464 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002465 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302466 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002467 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302468 log.Fields{
2469 "intf-id": intfID,
2470 "onu-id": onuID,
2471 "serial-num": serialNum,
2472 "onu": onu,
2473 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002474 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002475}
2476
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302477//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302478func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002479
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002480 f.onuGemInfoLock.Lock()
2481 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002482
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302484 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002485 "gem-port-id": gemPort,
2486 "intf-id": intfID,
2487 "onu-id": onuID,
2488 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002489 "onu-gem": f.onuGemInfo})
2490 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302491 // update the gem to the local cache as well as to kv strore
2492 for idx, onu := range onugem {
2493 if onu.OnuID == onuID {
2494 // check if gem already exists , else update the cache and kvstore
2495 for _, gem := range onu.GemPorts {
2496 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002497 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302498 log.Fields{
2499 "gem": gemPort,
2500 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302501 return
2502 }
2503 }
2504 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002505 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002506 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 }
2508 }
npujarec5762e2020-01-01 14:08:48 +05302509 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302510 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302512 log.Fields{
2513 "intf-id": intfID,
2514 "onu-id": onuID,
2515 "gemPort": gemPort,
2516 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002517 return
2518 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002519 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302520 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002521 "gem-port-id": gemPort,
2522 "intf-id": intfID,
2523 "onu-id": onuID,
2524 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002525 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002526}
2527
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002528//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302529func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002531 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002532 var err error
2533
2534 if packetIn.IntfType == "pon" {
2535 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002536 // get onu and uni ids associated with the given pon and gem ports
2537 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002538 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002539 return logicalPortNum, err
2540 }
Esin Karamandf392e12020-12-16 13:33:09 +00002541 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2542
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543 if packetIn.PortNo != 0 {
2544 logicalPortNum = packetIn.PortNo
2545 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002546 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002547 }
2548 // 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 +00002549 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002551 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002553
2554 if logger.V(log.DebugLevel) {
2555 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2556 log.Fields{
2557 "logical-port-num": logicalPortNum,
2558 "intf-type": packetIn.IntfType,
2559 "packet": hex.EncodeToString(packetIn.Pkt),
2560 })
2561 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002562 return logicalPortNum, nil
2563}
2564
Esin Karamandf392e12020-12-16 13:33:09 +00002565//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2566func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2567 key := gemPortKey{
2568 intfID: intfID,
2569 gemPort: gemPortID,
2570 }
2571 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2572 if ok {
2573 if len(uniPortInfo) > 1 {
2574 //return onu ID and uni port from the cache
2575 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2576 log.Fields{
2577 "intfID": intfID,
2578 "gemPortID": gemPortID,
2579 "onuID, uniID": uniPortInfo})
2580 return uniPortInfo[0], uniPortInfo[1], nil
2581 }
2582 }
2583 //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.
2584 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2585 if err == nil {
2586 f.toGemToUniMap(ctx, key, onuID, uniID)
2587 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2588 log.Fields{
2589 "gemPortKey": key,
2590 "onuID": onuID,
2591 "uniID": uniID})
2592 return onuID, uniID, nil
2593 }
2594 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2595 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2596 errors.New("no uni port found"))
2597}
2598
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002599//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002600func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002601 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002602
2603 ctag, priority, err := getCTagFromPacket(ctx, packet)
2604 if err != nil {
2605 return 0, err
2606 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302607
Esin Karaman7fb80c22020-07-16 14:23:33 +00002608 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002609 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002610 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002611 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002612 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302613 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302615 log.Fields{
2616 "pktinkey": pktInkey,
2617 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002618
2619 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302621 //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 +00002622 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302623 if err == nil {
2624 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002625 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002627 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002628 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302629 log.Fields{
2630 "pktinkey": pktInkey,
2631 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 return gemPortID, nil
2633 }
2634 }
Shrey Baid26912972020-04-16 21:02:31 +05302635 return uint32(0), olterrors.NewErrNotFound("gem-port",
2636 log.Fields{
2637 "pktinkey": pktInkey,
2638 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002639
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002640}
2641
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002642func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2643 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002644 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002645 classifier[PacketTagType] = DoubleTag
2646 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 /* We manage flowId resource pool on per PON port basis.
2648 Since this situation is tricky, as a hack, we pass the NNI port
2649 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002650 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002651 on NNI port, use onu_id as -1 (invalid)
2652 ****************** CAVEAT *******************
2653 This logic works if the NNI Port Id falls within the same valid
2654 range of PON Port Ids. If this doesn't work for some OLT Vendor
2655 we need to have a re-look at this.
2656 *********************************************
2657 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002658 onuID := -1
2659 uniID := -1
2660 gemPortID := -1
2661 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002662 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302663 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302664 return olterrors.NewErrNotFound("nni-intreface-id",
2665 log.Fields{
2666 "classifier": classifier,
2667 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002668 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302669 }
2670
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002671 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002672 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002673 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002675
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002676 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2677 log.Fields{
2678 "classifier": classifier,
2679 "action": action,
2680 "flowId": logicalFlow.Id,
2681 "intf-id": networkInterfaceID})
2682
David K. Bainbridge794735f2020-02-11 21:01:37 -08002683 classifierProto, err := makeOpenOltClassifierField(classifier)
2684 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002685 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002686 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002687 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002688 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002690 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002691 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002692 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002693 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2694 OnuId: int32(onuID), // OnuId not required
2695 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002696 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002697 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002698 AllocId: int32(allocID), // AllocId not used
2699 NetworkIntfId: int32(networkInterfaceID),
2700 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002701 Classifier: classifierProto,
2702 Action: actionProto,
2703 Priority: int32(logicalFlow.Priority),
2704 Cookie: logicalFlow.Cookie,
2705 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002706 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002707 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002708 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002709 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002710 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2711 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2712 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002713 }
2714 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002716
Esin Karamanae41e2b2019-12-17 18:13:13 +00002717//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2718func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2719 var packetType string
2720 ovid, ivid := false, false
2721 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2722 vid := vlanID & VlanvIDMask
2723 if vid != ReservedVlan {
2724 ovid = true
2725 }
2726 }
2727 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2728 vid := uint32(metadata)
2729 if vid != ReservedVlan {
2730 ivid = true
2731 }
2732 }
2733 if ovid && ivid {
2734 packetType = DoubleTag
2735 } else if !ovid && !ivid {
2736 packetType = Untagged
2737 } else {
2738 packetType = SingleTag
2739 }
2740 return packetType
2741}
2742
2743//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002744func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002745 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002746 action := make(map[string]interface{})
2747 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2748 action[TrapToHost] = true
2749 /* We manage flowId resource pool on per PON port basis.
2750 Since this situation is tricky, as a hack, we pass the NNI port
2751 index (network_intf_id) as PON port Index for the flowId resource
2752 pool. Also, there is no ONU Id available for trapping packets
2753 on NNI port, use onu_id as -1 (invalid)
2754 ****************** CAVEAT *******************
2755 This logic works if the NNI Port Id falls within the same valid
2756 range of PON Port Ids. If this doesn't work for some OLT Vendor
2757 we need to have a re-look at this.
2758 *********************************************
2759 */
2760 onuID := -1
2761 uniID := -1
2762 gemPortID := -1
2763 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002764 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002765 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302766 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002767 "classifier": classifier,
2768 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002769 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002770 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002771 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002772 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002773 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002774 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002775
David K. Bainbridge794735f2020-02-11 21:01:37 -08002776 classifierProto, err := makeOpenOltClassifierField(classifier)
2777 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002778 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002780 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002781 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002783 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002786 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2787 OnuId: int32(onuID), // OnuId not required
2788 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002789 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002790 FlowType: Downstream,
2791 AllocId: int32(allocID), // AllocId not used
2792 NetworkIntfId: int32(networkInterfaceID),
2793 GemportId: int32(gemPortID), // GemportId not used
2794 Classifier: classifierProto,
2795 Action: actionProto,
2796 Priority: int32(logicalFlow.Priority),
2797 Cookie: logicalFlow.Cookie,
2798 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002799 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002800 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002802 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002803 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2804 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2805 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002806 }
2807 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002808}
2809
salmansiddiqui7ac62132019-08-22 03:58:50 +00002810func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2811 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302812 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002813 }
2814 if Dir == tp_pb.Direction_UPSTREAM {
2815 return "upstream", nil
2816 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2817 return "downstream", nil
2818 }
2819 return "", nil
2820}
2821
Kent Hagermane6ff1012020-07-14 15:07:53 -04002822// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302823func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002824 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002825 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002826 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002827 intfID := args[IntfID]
2828 onuID := args[OnuID]
2829 uniID := args[UniID]
2830 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002831 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002832 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002833 gemToAes := make(map[uint32]bool)
2834
2835 var attributes []tp.IGemPortAttribute
2836 var direction = tp_pb.Direction_UPSTREAM
2837 switch TpInst := TpInst.(type) {
2838 case *tp.TechProfile:
2839 if IsUpstream(actionInfo[Output].(uint32)) {
2840 attributes = TpInst.UpstreamGemPortAttributeList
2841 } else {
2842 attributes = TpInst.DownstreamGemPortAttributeList
2843 direction = tp_pb.Direction_DOWNSTREAM
2844 }
2845 default:
2846 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2847 return
2848 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002849
2850 if len(gemPorts) == 1 {
2851 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002852 gemPortID = gemPorts[0]
2853 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002854 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2855 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002856 pBitMap := attributes[idx].PbitMap
2857 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2858 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2859 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2860 // this pcp bit traffic.
2861 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2862 if pbitSet == pbit1 {
2863 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2864 pbitToGem[pcp] = gemID
2865 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002866 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002867 }
2868 }
2869 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002870 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2871 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2872 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2873 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002874 }
2875
Gamze Abaka7650be62021-02-26 10:50:36 +00002876 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2877 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2878
salmansiddiqui7ac62132019-08-22 03:58:50 +00002879 if ipProto, ok := classifierInfo[IPProto]; ok {
2880 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002881 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002882 "tp-id": tpID,
2883 "alloc-id": allocID,
2884 "intf-id": intfID,
2885 "onu-id": onuID,
2886 "uni-id": uniID,
2887 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002888 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002889 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002890 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002891 }
2892
Girish Gowdra32625212020-04-29 11:26:35 -07002893 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302895 log.Fields{
2896 "intf-id": intfID,
2897 "onu-id": onuID,
2898 "uni-id": uniID,
2899 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002900 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002902 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002904 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 return
2906 }
2907 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002908 if ethType.(uint32) == EapEthType {
2909 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002910 "intf-id": intfID,
2911 "onu-id": onuID,
2912 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002913 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002914 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002915 var vlanID uint32
2916 if val, ok := classifierInfo[VlanVid]; ok {
2917 vlanID = (val.(uint32)) & VlanvIDMask
2918 } else {
2919 vlanID = DefaultMgmtVlan
2920 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002921 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002922 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002923 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002924 } else if ethType.(uint32) == PPPoEDEthType {
2925 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2926 "tp-id": tpID,
2927 "alloc-id": allocID,
2928 "intf-id": intfID,
2929 "onu-id": onuID,
2930 "uni-id": uniID,
2931 })
2932 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002933 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002934 logger.Warn(ctx, err)
2935 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002937 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002938 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002939 "intf-id": intfID,
2940 "onu-id": onuID,
2941 "uni-id": uniID,
2942 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002943 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002944 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002945 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002946 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002947 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002948 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002949 "intf-id": intfID,
2950 "onu-id": onuID,
2951 "uni-id": uniID,
2952 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002953 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002954 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002955 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002956 }
2957 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002958 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302959 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002960 "intf-id": intfID,
2961 "onu-id": onuID,
2962 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302963 "classifier": classifierInfo,
2964 "action": actionInfo,
2965 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002966 return
2967 }
2968 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002969 go func() {
2970 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2971 logger.Warn(ctx, err)
2972 }
2973 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974}
2975
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002976func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2977 f.flowsUsedByGemPortKey.RLock()
2978 flowIDList := f.flowsUsedByGemPort[gemPortID]
2979 f.flowsUsedByGemPortKey.RUnlock()
2980 return len(flowIDList) > 1
2981
Gamze Abakafee36392019-10-03 11:17:24 +00002982}
2983
npujarec5762e2020-01-01 14:08:48 +05302984func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2985 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002986 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2987 for _, currentGemPort := range currentGemPorts {
2988 for _, tpGemPort := range tpGemPorts {
2989 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2990 return true, currentGemPort
2991 }
2992 }
2993 }
Girish Gowdra54934262019-11-13 14:19:55 +05302994 if tpInst.InstanceCtrl.Onu == "single-instance" {
2995 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002996 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002997 logger.Warn(ctx, err)
2998 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002999 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003000 logger.Warn(ctx, err)
3001 }
Girish Gowdra54934262019-11-13 14:19:55 +05303002
3003 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3004 // still be used on other uni ports.
3005 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3006 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003007 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003008 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303009 for i := 0; i < len(tpInstances); i++ {
3010 tpI := tpInstances[i]
3011 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303012 for _, tpGemPort := range tpGemPorts {
3013 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303015 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303016 }
3017 }
3018 }
3019 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003020 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003021 return false, 0
3022}
3023
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003025 for _, field := range flows.GetOfbFields(flow) {
3026 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003029 } else if field.Type == flows.ETH_DST {
3030 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003032 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003035 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003038 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303039 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003041 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003044 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003047 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003049 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003050 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003052 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003053 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003056 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003057 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003059 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 return
3065 }
3066 }
3067}
3068
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003070 for _, action := range flows.GetActions(flow) {
3071 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003073 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003076 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 }
Scott Baker355d1742019-10-24 10:57:52 -07003078 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003079 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003081 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 if out := action.GetPush(); out != nil {
3083 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 } else {
3086 actionInfo[PushVlan] = true
3087 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303089 log.Fields{
3090 "push-tpid": actionInfo[TPID].(uint32),
3091 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 }
3093 }
Scott Baker355d1742019-10-24 10:57:52 -07003094 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 if out := action.GetSetField(); out != nil {
3096 if field := out.GetField(); field != nil {
3097 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003098 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3101 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 }
3103 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003104 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003107 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
3109 }
3110 return nil
3111}
3112
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003114 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003115 fieldtype := ofbField.GetType()
3116 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003117 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3118 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003122 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003123 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3124 pcp := ofbField.GetVlanPcp()
3125 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003126 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003129 }
3130 }
3131}
3132
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 } else {
3137 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003139 }
3140}
3141
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003143 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003145 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3146 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003147 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303150 log.Fields{
3151 "newinport": classifierInfo[InPort].(uint32),
3152 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003153 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303154 return olterrors.NewErrNotFound("child-in-port",
3155 log.Fields{
3156 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3157 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 }
3159 }
3160 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003162 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003163 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003164 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003165 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003166 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303167 log.Fields{
3168 "newoutport": actionInfo[Output].(uint32),
3169 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003170 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303171 return olterrors.NewErrNotFound("out-port",
3172 log.Fields{
3173 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3174 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003175 }
3176 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3177 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003178 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003179 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303181 log.Fields{
3182 "newinport": actionInfo[Output].(uint32),
3183 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003184 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303185 return olterrors.NewErrNotFound("nni-port",
3186 log.Fields{
3187 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3188 "in-port": classifierInfo[InPort].(uint32),
3189 "out-port": actionInfo[Output].(uint32),
3190 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 }
3192 }
3193 }
3194 return nil
3195}
Gamze Abakafee36392019-10-03 11:17:24 +00003196
Neha Sharma96b7bf22020-06-15 10:37:32 +00003197func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003198 /* Metadata 8 bytes:
3199 Most Significant 2 Bytes = Inner VLAN
3200 Next 2 Bytes = Tech Profile ID(TPID)
3201 Least Significant 4 Bytes = Port ID
3202 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3203 subscriber related flows.
3204 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003206 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003207 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003208 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003209 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003210 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003211}
3212
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3214 for _, sliceElement := range slice {
3215 if sliceElement == item {
3216 return slice
3217 }
3218 }
3219 return append(slice, item)
3220}
3221
3222func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003223 for _, sliceElement := range slice {
3224 if sliceElement == item {
3225 return slice
3226 }
3227 }
3228 return append(slice, item)
3229}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303230
3231// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303233
3234 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3235 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003236 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003237 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003238 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003239 log.Fields{
3240 "port-number": action[Output].(uint32),
3241 "error": err})
3242 return uint32(0), err
3243 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003244 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303245 return intfID, nil
3246 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003250 log.Fields{
3251 "port-number": action[Output].(uint32),
3252 "error": err})
3253 return uint32(0), err
3254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303256 return intfID, nil
3257 }
3258 return uint32(0), nil
3259}
3260
3261// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003262func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3263 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3264 if err != nil {
3265 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3266 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3267 return
3268 }
3269 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003270
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003271 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003272 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003273 f.packetInGemPortLock.RUnlock()
3274
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303275 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003276 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003277 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 +05303278 log.Fields{
3279 "pktinkey": pktInkey,
3280 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003281 return
3282 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003284 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003285 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003286 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003287
npujarec5762e2020-01-01 14:08:48 +05303288 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003289 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 +05303290 log.Fields{
3291 "pktinkey": pktInkey,
3292 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303293}
3294
Esin Karaman7fb80c22020-07-16 14:23:33 +00003295//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3296func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3297 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003298 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003299 return 0, 0, errors.New("invalid packet length")
3300 }
3301 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3302 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3303
3304 var index int8
3305 if outerEthType == 0x8100 {
3306 if innerEthType == 0x8100 {
3307 // q-in-q 802.1ad or 802.1q double tagged packet.
3308 // get the inner vlanId
3309 index = 18
3310 } else {
3311 index = 14
3312 }
3313 priority := (packet[index] >> 5) & 0x7
3314 //13 bits composes vlanId value
3315 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3316 return vlan, priority, nil
3317 }
3318 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3319 return 0, 0, nil
3320}
3321
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303322// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303323func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003324
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003325 f.onuGemInfoLock.Lock()
3326 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003327
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303329 for idx, onu := range onugem {
3330 if onu.OnuID == onuID {
3331 for _, uni := range onu.UniPorts {
3332 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003333 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 +05303334 return
3335 }
3336 }
3337 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003338 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303339 }
3340 }
npujarec5762e2020-01-01 14:08:48 +05303341 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003342
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303343}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303344
npujarec5762e2020-01-01 14:08:48 +05303345func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3346 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303347 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003348 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303349 return
3350 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003351 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303352 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003353 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303354 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003355 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303356}
Esin Karamanccb714b2019-11-29 15:02:06 +00003357
Girish Gowdra9602eb42020-09-09 15:50:39 -07003358//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3359// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003360func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003361 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003362 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003363 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3364 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3365
Esin Karamanccb714b2019-11-29 15:02:06 +00003366 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003367 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 -07003368 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003369 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003370
3371 var onuID = int32(NoneOnuID)
3372 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003373 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3374 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3375 log.Fields{
3376 "flow": flow,
3377 "device-id": f.deviceHandler.device.Id,
3378 "intf-id": networkInterfaceID,
3379 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003380 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003381 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3382 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3383 log.Fields{
3384 "flow": flowInfo.Flow,
3385 "flow-id": flow.Id,
3386 "device-id": f.deviceHandler.device.Id})
3387 // Remove from device
3388 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3389 // DKB
3390 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3391 log.Fields{
3392 "flow-id": flow.Id,
3393 "error": err})
3394 return err
3395 }
3396 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003397 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003398}
3399
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003400// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3401func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3402 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3403 if err != nil {
3404 _ = olterrors.NewErrNotFound("onu", log.Fields{
3405 "pon-port": f.ponPortIdx}, err).Log()
3406 return
3407 }
3408
3409 f.subscriberDataPathFlowIDMapLock.Lock()
3410 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3411
3412 for _, onu := range onuGemInfo {
3413 for _, uniID := range onu.UniPorts {
3414 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3415 if err != nil {
3416 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3417 }
3418 for _, flowID := range flowIDs {
3419 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3420 if flowInfo == nil {
3421 // Error is already logged in the called function
3422 continue
3423 }
3424 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3425 flowInfo.Flow.FlowType == Downstream &&
3426 flowInfo.Flow.Classifier.OVid > 0 &&
3427 flowInfo.Flow.TechProfileId > 0 {
3428 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3429 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3430 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3431 }
3432 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3433 flowInfo.Flow.FlowType == Upstream &&
3434 flowInfo.Flow.Action.OVid > 0 &&
3435 flowInfo.Flow.TechProfileId > 0 {
3436 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3437 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3438 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3439 }
3440 }
3441 }
3442 }
3443 }
3444}
3445
3446// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3447func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3448 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3449}