blob: 680df663f23068be6a7adeeed4078665e076121f [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
28
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
30 "github.com/opencord/voltha-lib-go/v4/pkg/log"
31 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080032 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070033 "github.com/opencord/voltha-protos/v4/go/common"
34 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
35 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
36 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
37 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
38 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040039
Thomas Lee S94109f12020-03-03 16:39:29 +053040 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000041 "google.golang.org/grpc/codes"
42 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053043)
44
45const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070046 //IPProtoDhcp flow category
47 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053048
Girish Gowdraa09aeab2020-09-14 16:30:52 -070049 //IgmpProto proto value
50 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051
52 //EapEthType eapethtype value
53 EapEthType = 0x888e
54 //LldpEthType lldp ethtype value
55 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000056 //IPv4EthType IPv4 ethernet type value
57 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030058 //PPPoEDEthType PPPoE discovery ethernet type value
59 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060
Andrea Campanella7acc0b92020-02-14 09:20:49 +010061 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
62 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040063
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064 //DefaultMgmtVlan default vlan value
65 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053066
manikkaraj kbf256be2019-03-25 00:13:48 +053067 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068
David K. Bainbridge82efc492019-09-04 09:57:11 -070069 //Upstream constant
70 Upstream = "upstream"
71 //Downstream constant
72 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000073 //Multicast constant
74 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 //PacketTagType constant
76 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070077 //Untagged constant
78 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //SingleTag constant
80 SingleTag = "single_tag"
81 //DoubleTag constant
82 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053083
84 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070085
86 //EthType constant
87 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000088 //EthDst constant
89 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070090 //TPID constant
91 TPID = "tpid"
92 //IPProto constant
93 IPProto = "ip_proto"
94 //InPort constant
95 InPort = "in_port"
96 //VlanVid constant
97 VlanVid = "vlan_vid"
98 //VlanPcp constant
99 VlanPcp = "vlan_pcp"
100
101 //UDPDst constant
102 UDPDst = "udp_dst"
103 //UDPSrc constant
104 UDPSrc = "udp_src"
105 //Ipv4Dst constant
106 Ipv4Dst = "ipv4_dst"
107 //Ipv4Src constant
108 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700109 //Metadata constant
110 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700111 //TunnelID constant
112 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Output constant
114 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000115 //GroupID constant
116 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 // Actions
118
119 //PopVlan constant
120 PopVlan = "pop_vlan"
121 //PushVlan constant
122 PushVlan = "push_vlan"
123 //TrapToHost constant
124 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400125 //MaxMeterBand constant
126 MaxMeterBand = 2
127 //VlanPCPMask contant
128 VlanPCPMask = 0xFF
129 //VlanvIDMask constant
130 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000131 //IntfID constant
132 IntfID = "intfId"
133 //OnuID constant
134 OnuID = "onuId"
135 //UniID constant
136 UniID = "uniId"
137 //PortNo constant
138 PortNo = "portNo"
139 //AllocID constant
140 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000141 //GemID constant
142 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000143
144 //NoneOnuID constant
145 NoneOnuID = -1
146 //NoneUniID constant
147 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700148
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700149 // Max number of flows that can be queued per ONU
150 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530151
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700152 bitMapPrefix = "0b"
153 pbit1 = '1'
154)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400155
Esin Karamandf392e12020-12-16 13:33:09 +0000156type gemPortKey struct {
157 intfID uint32
158 gemPort uint32
159}
160
Gamze Abakafee36392019-10-03 11:17:24 +0000161type schedQueue struct {
162 direction tp_pb.Direction
163 intfID uint32
164 onuID uint32
165 uniID uint32
166 tpID uint32
167 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700168 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000169 meterID uint32
170 flowMetadata *voltha.FlowMetadata
171}
172
Gamze Abaka7650be62021-02-26 10:50:36 +0000173type flowContext struct {
174 intfID uint32
175 onuID uint32
176 uniID uint32
177 portNo uint32
178 classifier map[string]interface{}
179 action map[string]interface{}
180 logicalFlow *ofp.OfpFlowStats
181 allocID uint32
182 gemPortID uint32
183 tpID uint32
184 pbitToGem map[uint32]uint32
185 gemToAes map[uint32]bool
186}
187
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700188// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
189type subscriberDataPathFlowIDKey struct {
190 intfID uint32
191 onuID uint32
192 uniID uint32
193 direction string
194 tpID uint32
195}
196
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700197// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
198// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
199// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
200// flow and processes it serially
201type flowControlBlock struct {
202 ctx context.Context // Flow handler context
203 addFlow bool // if true flow to be added, else removed
204 flow *voltha.OfpFlowStats // Flow message
205 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
206 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000207}
208
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700209//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530210type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700211 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
212 techprofile map[uint32]tp.TechProfileIf
213 deviceHandler *DeviceHandler
214 grpMgr *OpenOltGroupMgr
215 resourceMgr *rsrcMgr.OpenOltResourceMgr
216
217 onuIdsLock sync.RWMutex // TODO: Do we need this?
218
219 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
220 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
221
222 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
223 packetInGemPortLock sync.RWMutex
224
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700225 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700227 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700228 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
231 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
232 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
233 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700234
235 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
236 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
237 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000238
239 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
240 gemToUniMap map[gemPortKey][]uint32
241 //We need to have a global lock on the gemToUniLock map
242 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530243}
244
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700245//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700246func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000247 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530248 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 var err error
250 var idx uint32
251
manikkaraj kbf256be2019-03-25 00:13:48 +0530252 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700253 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530254 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000255 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000256 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
257 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530258 return nil
259 }
William Kurkian740a09c2019-10-23 17:07:38 -0400260 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700261 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700263 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700264 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700265 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
266 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700267
268 // Create a slice of buffered channels for handling concurrent flows per ONU.
269 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
270 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
271 for i := range flowMgr.incomingFlows {
272 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
273 // Spin up a go routine to handling incoming flows (add/remove).
274 // There will be on go routine per ONU.
275 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
276 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
277 }
278
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530279 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700280 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
281 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530282 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700283 //Load flowID list per gem map per interface from the kvstore.
284 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000285 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000286
287 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
288 flowMgr.gemToUniLock = sync.RWMutex{}
289
Girish Gowdra9602eb42020-09-09 15:50:39 -0700290 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700291 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000292 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530293 return &flowMgr
294}
295
Esin Karamandf392e12020-12-16 13:33:09 +0000296// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
297func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
298 f.gemToUniLock.Lock()
299 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
300 f.gemToUniLock.Unlock()
301}
302
303// fromGemToUniMap returns onu and uni ID associated with the given key
304func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
305 f.gemToUniLock.RLock()
306 defer f.gemToUniLock.RUnlock()
307 val, ok := f.gemToUniMap[key]
308 return val, ok
309}
310
311// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
312func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
313 f.gemToUniLock.Lock()
314 defer f.gemToUniLock.Unlock()
315 delete(f.gemToUniMap, key)
316}
317
Kent Hagermane6ff1012020-07-14 15:07:53 -0400318func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700319 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
320 // Flow is not replicated in this case, we need to register the flow for a single gem-port
321 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
322 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
323 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
324 for _, gemPort := range deviceFlow.PbitToGemport {
325 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
326 return err
327 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700328 }
Gamze Abakafee36392019-10-03 11:17:24 +0000329 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700330 return nil
331}
332
333func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
334 f.flowsUsedByGemPortKey.Lock()
335 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
336 if !ok {
337 flowIDList = []uint64{flowFromCore.Id}
338 }
339 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
340 f.flowsUsedByGemPort[gemPortID] = flowIDList
341 f.flowsUsedByGemPortKey.Unlock()
342
343 // update the flowids for a gem to the KVstore
344 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400345}
346
Girish Gowdra9602eb42020-09-09 15:50:39 -0700347func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000348 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200349 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000350 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530351 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700352 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530353
Neha Sharma96b7bf22020-06-15 10:37:32 +0000354 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530355 "device-id": f.deviceHandler.device.Id,
356 "intf-id": intfID,
357 "onu-id": onuID,
358 "uni-id": uniID,
359 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700360 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530361 "action": actionInfo,
362 "usmeter-iD": UsMeterID,
363 "dsmeter-iD": DsMeterID,
364 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400365 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
366 // is because the flow is an NNI flow and there would be no onu resources associated with it
367 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400368 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200369 cause := "no-onu-id-for-flow"
370 fields := log.Fields{
371 "onu": onuID,
372 "port-no": portNo,
373 "classifer": classifierInfo,
374 "action": actionInfo,
375 "device-id": f.deviceHandler.device.Id}
376 logger.Errorw(ctx, cause, fields)
377 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530378 }
379
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700380 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000381 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530382 "uni": uni,
383 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530384
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700385 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
386 "device-id": f.deviceHandler.device.Id,
387 "intf-id": intfID,
388 "onu-id": onuID,
389 "uni-id": uniID,
390 "port-no": portNo,
391 "classifier": classifierInfo,
392 "action": actionInfo,
393 "usmeter-id": UsMeterID,
394 "dsmeter-id": DsMeterID,
395 "tp-id": TpID})
396 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
397 if allocID == 0 || gemPorts == nil || TpInst == nil {
398 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
399 return olterrors.NewErrNotFound(
400 "alloc-id-gem-ports-tp-unavailable",
401 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700403 args := make(map[string]uint32)
404 args[IntfID] = intfID
405 args[OnuID] = onuID
406 args[UniID] = uniID
407 args[PortNo] = portNo
408 args[AllocID] = allocID
409
410 /* Flows can be added specific to gemport if p-bits are received.
411 * If no pbit mentioned then adding flows for all gemports
412 */
413 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
414
Andrea Campanellabfe08432020-09-11 17:07:03 +0200415 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530416}
417
salmansiddiqui7ac62132019-08-22 03:58:50 +0000418// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530419func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400420
Neha Sharma96b7bf22020-06-15 10:37:32 +0000421 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530422 log.Fields{"dir": sq.direction,
423 "intf-id": sq.intfID,
424 "onu-id": sq.onuID,
425 "uni-id": sq.uniID,
426 "tp-id": sq.tpID,
427 "meter-id": sq.meterID,
428 "tp-inst": sq.tpInst,
429 "flowmetadata": sq.flowMetadata,
430 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431
Gamze Abakafee36392019-10-03 11:17:24 +0000432 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000433 if err != nil {
434 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 }
436
437 /* Lets make a simple assumption that if the meter-id is present on the KV store,
438 * then the scheduler and queues configuration is applied on the OLT device
439 * in the given direction.
440 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000441
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530443 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530445 return olterrors.NewErrNotFound("meter",
446 log.Fields{"intf-id": sq.intfID,
447 "onu-id": sq.onuID,
448 "uni-id": sq.uniID,
449 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000451
Manikkaraj kb1d51442019-07-23 10:41:02 -0400452 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000453 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000454 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 "unsupported": "meter-id",
459 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530460 "meter-id-in-flow": sq.meterID,
461 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000463
Neha Sharma96b7bf22020-06-15 10:37:32 +0000464 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530465 log.Fields{
466 "meter-id": sq.meterID,
467 "direction": Direction,
468 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000469
Gamze Abakafee36392019-10-03 11:17:24 +0000470 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000471 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000472 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000475
476 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530477 return olterrors.NewErrNotFound("scheduler-config",
478 log.Fields{
479 "intf-id": sq.intfID,
480 "direction": sq.direction,
481 "tp-inst": sq.tpInst,
482 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000483 }
484
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000486 if sq.flowMetadata != nil {
487 for _, meter := range sq.flowMetadata.Meters {
488 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000490 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530491 log.Fields{"meterConfig": meterConfig,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 break
494 }
495 }
496 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000497 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 }
499 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530500 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800501 "reason": "Could-not-get-meterbands-from-flowMetadata",
502 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530503 "meter-id": sq.meterID,
504 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400505 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000506 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530507 log.Fields{"Bands": meterConfig.Bands,
508 "meter-id": sq.meterID,
509 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530510 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800511 "reason": "Invalid-number-of-bands-in-meter",
512 "meterband-count": len(meterConfig.Bands),
513 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530514 "meter-id": sq.meterID,
515 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 }
517 cir := meterConfig.Bands[0].Rate
518 cbs := meterConfig.Bands[0].BurstSize
519 eir := meterConfig.Bands[1].Rate
520 ebs := meterConfig.Bands[1].BurstSize
521 pir := cir + eir
522 pbs := cbs + ebs
523 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
524
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700525 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000526 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400527
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700528 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530529 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
530 log.Fields{"intf-id": sq.intfID,
531 "direction": sq.direction,
532 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400533 }
534
salmansiddiqui7ac62132019-08-22 03:58:50 +0000535 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400536 * store the meter id on the KV store, for further reference.
537 */
npujarec5762e2020-01-01 14:08:48 +0530538 if err := f.resourceMgr.UpdateMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterConfig); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530539 return olterrors.NewErrAdapter("failed-updating-meter-id",
540 log.Fields{"onu-id": sq.onuID,
541 "meter-id": sq.meterID,
542 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400543 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000544 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530545 log.Fields{"direction": Direction,
546 "Meter": meterConfig,
547 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400548 return nil
549}
550
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700551func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000552 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553
554 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530555 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
556 log.Fields{"intf-id": sq.intfID,
557 "direction": sq.direction,
558 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000559 }
560
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530562 log.Fields{
563 "direction": sq.direction,
564 "TrafficScheds": TrafficSched,
565 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530566 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000567 IntfId: sq.intfID, OnuId: sq.onuID,
568 UniId: sq.uniID, PortNo: sq.uniPort,
569 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000570 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530573 "direction": sq.direction,
574 "traffic-queues": trafficQueues,
575 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576
577 // On receiving the CreateTrafficQueues request, the driver should create corresponding
578 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000579 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530580 log.Fields{"direction": sq.direction,
581 "traffic-queues": trafficQueues,
582 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530583 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000584 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
585 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000586 TrafficQueues: trafficQueues,
587 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530588 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000589 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000590 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530591 "direction": sq.direction,
592 "traffic-queues": trafficQueues,
593 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594
Esin Karamanccb714b2019-11-29 15:02:06 +0000595 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000596 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000597 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700598 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000599 //assumed that there is only one queue per PON for the multicast service
600 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
601 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700604 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000605 gemPortID: multicastQueuePerPonPort.GemportId,
606 servicePriority: multicastQueuePerPonPort.Priority,
607 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700608 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000609 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400610 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
611 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
612 return err
613 }
Shrey Baid26912972020-04-16 21:02:31 +0530614
Neha Sharma96b7bf22020-06-15 10:37:32 +0000615 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000616 }
617 }
618 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000619 return nil
620}
621
salmansiddiqui7ac62132019-08-22 03:58:50 +0000622// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530623func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400624
625 var Direction string
626 var SchedCfg *tp_pb.SchedulerConfig
627 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000628 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530629 log.Fields{
630 "direction": sq.direction,
631 "intf-id": sq.intfID,
632 "onu-id": sq.onuID,
633 "uni-id": sq.uniID,
634 "uni-port": sq.uniPort,
635 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000636 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000637 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400638 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000639 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000640 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 Direction = "downstream"
642 }
643
Girish Kumar8f73fe02019-12-09 13:19:37 +0000644 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530645 return olterrors.NewErrNotFound("scheduler-config",
646 log.Fields{
647 "int-id": sq.intfID,
648 "direction": sq.direction,
649 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000650 }
651
npujarec5762e2020-01-01 14:08:48 +0530652 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400653 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530654 return olterrors.NewErrNotFound("meter",
655 log.Fields{
656 "onu-id": sq.onuID,
657 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400658 }
659 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000660 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530661 log.Fields{
662 "direction": Direction,
663 "intf-id": sq.intfID,
664 "onu-id": sq.onuID,
665 "uni-id": sq.uniID,
666 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400667 return nil
668 }
669 cir := KVStoreMeter.Bands[0].Rate
670 cbs := KVStoreMeter.Bands[0].BurstSize
671 eir := KVStoreMeter.Bands[1].Rate
672 ebs := KVStoreMeter.Bands[1].BurstSize
673 pir := cir + eir
674 pbs := cbs + ebs
675
676 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
677
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700678 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000679 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000680
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000682 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530683 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
684 log.Fields{
685 "intf-id": sq.intfID,
686 "direction": sq.direction,
687 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000688 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689
npujarec5762e2020-01-01 14:08:48 +0530690 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000691 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
692 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000693 TrafficQueues: TrafficQueues,
694 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000695 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530696 log.Fields{
697 "intf-id": sq.intfID,
698 "traffic-queues": TrafficQueues,
699 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000701 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530702 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000703 IntfId: sq.intfID, OnuId: sq.onuID,
704 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000706 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530707 log.Fields{
708 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700709 "traffic-schedulers": TrafficSched,
710 "onu-id": sq.onuID,
711 "uni-id": sq.uniID,
712 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400713 }
714
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700715 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
716 log.Fields{"device-id": f.deviceHandler.device.Id,
717 "intf-id": sq.intfID,
718 "onu-id": sq.onuID,
719 "uni-id": sq.uniID,
720 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000721
722 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400723 * delete the meter id on the KV store.
724 */
npujarec5762e2020-01-01 14:08:48 +0530725 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400726 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530727 return olterrors.NewErrAdapter("unable-to-remove-meter",
728 log.Fields{
729 "onu": sq.onuID,
730 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700731 "device-id": f.deviceHandler.device.Id,
732 "intf-id": sq.intfID,
733 "onu-id": sq.onuID,
734 "uni-id": sq.uniID,
735 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000737 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530738 log.Fields{
739 "meter-id": KVStoreMeter.MeterId,
740 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700741 "device-id": f.deviceHandler.device.Id,
742 "intf-id": sq.intfID,
743 "onu-id": sq.onuID,
744 "uni-id": sq.uniID,
745 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400746 return err
747}
748
Gamze Abakafee36392019-10-03 11:17:24 +0000749// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700750func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000751 var allocIDs []uint32
752 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530753 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530754 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000755 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000756
npujarec5762e2020-01-01 14:08:48 +0530757 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
758 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000759 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530760
Neha Sharma96b7bf22020-06-15 10:37:32 +0000761 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530762 "intf-id": intfID,
763 "onu-id": onuID,
764 "uni-id": uniID,
765 "device-id": f.deviceHandler.device.Id,
766 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530767
Manikkaraj kb1d51442019-07-23 10:41:02 -0400768 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530769 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000770 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530772 log.Fields{
773 "path": tpPath,
774 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530775 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000776 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530777 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000778 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530779 log.Fields{
780 "error": err,
781 "tp-id": TpID,
782 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000783 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530784 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400785 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
786 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
787 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530788 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000789 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530790 log.Fields{
791 "uni": uni,
792 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530794 }
Gamze Abakafee36392019-10-03 11:17:24 +0000795
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700796 switch tpInst := techProfileInstance.(type) {
797 case *tp.TechProfile:
798 if UsMeterID != 0 {
799 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
800 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
801 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000802 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700803 log.Fields{
804 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700805 "onu-id": onuID,
806 "uni-id": uniID,
807 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700808 "meter-id": UsMeterID,
809 "device-id": f.deviceHandler.device.Id})
810 return 0, nil, nil
811 }
812 }
813 if DsMeterID != 0 {
814 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
815 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
816 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700818 log.Fields{
819 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700820 "onu-id": onuID,
821 "uni-id": uniID,
822 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700823 "meter-id": DsMeterID,
824 "device-id": f.deviceHandler.device.Id})
825 return 0, nil, nil
826 }
827 }
828 allocID := tpInst.UsScheduler.AllocID
829 for _, gem := range tpInst.UpstreamGemPortAttributeList {
830 gemPortIDs = append(gemPortIDs, gem.GemportID)
831 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700832 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000833
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834 if tpInstanceExists {
835 return allocID, gemPortIDs, techProfileInstance
836 }
837
838 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700839 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700840 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000841 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700842 log.Fields{
843 "alloc-ids": allocIDs,
844 "gemports": allgemPortIDs,
845 "device-id": f.deviceHandler.device.Id})
846 // Send Tconts and GEM ports to KV store
847 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530848 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700849 case *tp.EponProfile:
850 // CreateSchedulerQueues for EPON needs to be implemented here
851 // when voltha-protos for EPON is completed.
852 allocID := tpInst.AllocID
853 for _, gem := range tpInst.UpstreamQueueAttributeList {
854 gemPortIDs = append(gemPortIDs, gem.GemportID)
855 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700856 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857
858 if tpInstanceExists {
859 return allocID, gemPortIDs, techProfileInstance
860 }
861
862 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700863 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700864 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 log.Fields{
867 "alloc-ids": allocIDs,
868 "gemports": allgemPortIDs,
869 "device-id": f.deviceHandler.device.Id})
870 // Send Tconts and GEM ports to KV store
871 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
872 return allocID, gemPortIDs, techProfileInstance
873 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000874 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700875 log.Fields{
876 "tpInst": tpInst})
877 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530878 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530879}
880
npujarec5762e2020-01-01 14:08:48 +0530881func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530882
Neha Sharma96b7bf22020-06-15 10:37:32 +0000883 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530884 log.Fields{
885 "intf-id": intfID,
886 "onu-id": onuID,
887 "uni-id": uniID,
888 "alloc-id": allocID,
889 "gemport-ids": gemPortIDs,
890 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530891 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530892 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000893 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 +0530894 }
npujarec5762e2020-01-01 14:08:48 +0530895 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000896 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 +0530897 }
npujarec5762e2020-01-01 14:08:48 +0530898 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000899 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 +0000900 } else {
901 //add to gem to uni cache
902 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530903 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000904 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 -0400905 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530906 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400907 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530908}
909
Esin Karamandf392e12020-12-16 13:33:09 +0000910//addGemPortUniAssociationsToCache
911func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
912 for _, gemPortID := range gemPortIDs {
913 key := gemPortKey{
914 intfID: intfID,
915 gemPort: gemPortID,
916 }
917 f.toGemToUniMap(ctx, key, onuID, uniID)
918 }
919 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
920 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
921}
922
Neha Sharma96b7bf22020-06-15 10:37:32 +0000923func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000924 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530925 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000926 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700927 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400928 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000929 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530930 log.Fields{
931 "intf-id": intfID,
932 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530933 }
934 }
935 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400936 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530937 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530938 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800939 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530940 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
941 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530942 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000943 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530944 log.Fields{
945 "numofTech": tpCount,
946 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
947 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530948 return nil
949}
950
Gamze Abaka7650be62021-02-26 10:50:36 +0000951func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
952 flowContext.classifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000953 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530954 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000955 "uplinkClassifier": flowContext.classifier,
956 "uplinkAction": flowContext.action})
957 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530958 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530959}
960
Gamze Abaka7650be62021-02-26 10:50:36 +0000961func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
962 downlinkClassifier := flowContext.classifier
963 downlinkAction := flowContext.action
964
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700965 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000966 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530967 log.Fields{
968 "downlinkClassifier": downlinkClassifier,
969 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400970 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
971 if vlan, exists := downlinkClassifier[VlanVid]; exists {
972 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700973 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Gamze Abaka7650be62021-02-26 10:50:36 +0000974 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530976 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000977 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +0530978 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +0000979 "onu-id": flowContext.onuID,
980 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800981 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400982 }
983 }
984 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530985 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400986
Manikkaraj k884c1242019-04-11 16:26:42 +0530987 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700988 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400989 // vlan_vid is a uint32. must be type asserted as such or conversion fails
990 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530991 if ok {
992 downlinkAction[VlanVid] = dlClVid & 0xfff
993 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530994 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530995 "reason": "failed-to-convert-vlanid-classifier",
996 "vlan-id": VlanVid,
997 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530998 }
999
Gamze Abaka7650be62021-02-26 10:50:36 +00001000 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301001}
1002
Gamze Abaka7650be62021-02-26 10:50:36 +00001003func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001004
1005 var inverseDirection string
1006 if direction == Upstream {
1007 inverseDirection = Downstream
1008 } else {
1009 inverseDirection = Upstream
1010 }
1011
Gamze Abaka7650be62021-02-26 10:50:36 +00001012 intfID := flowContext.intfID
1013 onuID := flowContext.onuID
1014 uniID := flowContext.uniID
1015 classifier := flowContext.classifier
1016 action := flowContext.action
1017 allocID := flowContext.allocID
1018 gemPortID := flowContext.gemPortID
1019 tpID := flowContext.tpID
1020 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001021 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301022 log.Fields{
1023 "intf-id": intfID,
1024 "onu-id": onuID,
1025 "uni-id": uniID,
1026 "device-id": f.deviceHandler.device.Id,
1027 "classifier": classifier,
1028 "action": action,
1029 "direction": direction,
1030 "alloc-id": allocID,
1031 "gemport-id": gemPortID,
1032 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001033
1034 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001035 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301036 log.Fields{
1037 "device-id": f.deviceHandler.device.Id,
1038 "intf-id": intfID,
1039 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001040 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301041 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001042 classifierProto, err := makeOpenOltClassifierField(classifier)
1043 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301044 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301045 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001046 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301047 log.Fields{
1048 "classifier": *classifierProto,
1049 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001050 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001051 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301052 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301053 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001054 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301055 log.Fields{
1056 "action": *actionProto,
1057 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001058 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301059 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301060 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001061 log.Fields{
1062 "classifier": classifier,
1063 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301064 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301066 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001067
1068 // Get symmetric flowID if it exists
1069 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1070 // symmetric flow earlier
1071 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1072 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1073 f.subscriberDataPathFlowIDMapLock.RLock()
1074 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1075 f.subscriberDataPathFlowIDMapLock.RUnlock()
1076
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001077 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001078 OnuId: int32(onuID),
1079 UniId: int32(uniID),
1080 FlowId: logicalFlow.Id,
1081 FlowType: direction,
1082 AllocId: int32(allocID),
1083 NetworkIntfId: int32(networkIntfID),
1084 GemportId: int32(gemPortID),
1085 Classifier: classifierProto,
1086 Action: actionProto,
1087 Priority: int32(logicalFlow.Priority),
1088 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001089 PortNo: flowContext.portNo,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001090 TechProfileId: tpID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001091 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1092 PbitToGemport: flowContext.pbitToGem,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001093 SymmetricFlowId: symmFlowID,
Gamze Abaka7650be62021-02-26 10:50:36 +00001094 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001095 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301098 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001099 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301100 log.Fields{"direction": direction,
1101 "device-id": f.deviceHandler.device.Id,
1102 "flow": flow,
1103 "intf-id": intfID,
1104 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1106 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1107 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301108 log.Fields{
1109 "flow": flow,
1110 "device-id": f.deviceHandler.device.Id,
1111 "intf-id": intfID,
1112 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001114
1115 // Update the current flowID to the map
1116 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1117 f.subscriberDataPathFlowIDMapLock.Lock()
1118 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1119 f.subscriberDataPathFlowIDMapLock.Unlock()
1120
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301122}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001123
Gamze Abaka7650be62021-02-26 10:50:36 +00001124func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1125
1126 intfID := flowContext.intfID
1127 onuID := flowContext.onuID
1128 uniID := flowContext.uniID
1129 logicalFlow := flowContext.logicalFlow
1130 classifier := flowContext.classifier
1131 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132
Neha Sharma96b7bf22020-06-15 10:37:32 +00001133 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301134 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301135 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001136 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301137 "action": action,
1138 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001139 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301140 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301141
1142 // Clear the action map
1143 for k := range action {
1144 delete(action, k)
1145 }
1146
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001147 action[TrapToHost] = true
1148 classifier[UDPSrc] = uint32(68)
1149 classifier[UDPDst] = uint32(67)
1150 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301151
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001152 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301154 log.Fields{
1155 "device-id": f.deviceHandler.device.Id,
1156 "intf-id": intfID,
1157 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301159 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301160
Neha Sharma96b7bf22020-06-15 10:37:32 +00001161 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301162 log.Fields{
1163 "ul_classifier": classifier,
1164 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001165 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301166 "intf-id": intfID,
1167 "onu-id": onuID,
1168 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301169
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 classifierProto, err := makeOpenOltClassifierField(classifier)
1171 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301172 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301173 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001174 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001175 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301177 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301178 }
1179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 OnuId: int32(onuID),
1182 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001183 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001184 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001185 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001186 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001187 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 Classifier: classifierProto,
1189 Action: actionProto,
1190 Priority: int32(logicalFlow.Priority),
1191 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001192 PortNo: flowContext.portNo,
1193 TechProfileId: flowContext.tpID,
1194 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1195 PbitToGemport: flowContext.pbitToGem,
1196 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001197 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001198 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001199 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301202 log.Fields{
1203 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001204 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301205 "intf-id": intfID,
1206 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1208 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 +05301209 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1210 log.Fields{
1211 "flow": dhcpFlow,
1212 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301213 }
1214
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301216}
1217
Esin Karamanae41e2b2019-12-17 18:13:13 +00001218//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001219func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1220 delete(flowContext.classifier, VlanVid)
1221 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001222}
1223
1224//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001225func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1226
1227 intfID := flowContext.intfID
1228 onuID := flowContext.onuID
1229 uniID := flowContext.uniID
1230 logicalFlow := flowContext.logicalFlow
1231 classifier := flowContext.classifier
1232 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233
Neha Sharma96b7bf22020-06-15 10:37:32 +00001234 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301236 return olterrors.NewErrNotFound("nni-interface-id",
1237 log.Fields{
1238 "classifier": classifier,
1239 "action": action,
1240 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001242 }
1243
1244 // Clear the action map
1245 for k := range action {
1246 delete(action, k)
1247 }
1248
1249 action[TrapToHost] = true
1250 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001252 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001254 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001255 }
1256
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301258 log.Fields{
1259 "ul_classifier": classifier,
1260 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001261 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301262 "device-id": f.deviceHandler.device.Id,
1263 "intf-id": intfID,
1264 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265
David K. Bainbridge794735f2020-02-11 21:01:37 -08001266 classifierProto, err := makeOpenOltClassifierField(classifier)
1267 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301268 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001270 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301271 log.Fields{
1272 "classifier": *classifierProto,
1273 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001274 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
1278
David K. Bainbridge794735f2020-02-11 21:01:37 -08001279 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001280 OnuId: int32(onuID),
1281 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001282 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001283 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001284 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001286 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001287 Classifier: classifierProto,
1288 Action: actionProto,
1289 Priority: int32(logicalFlow.Priority),
1290 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001291 PortNo: flowContext.portNo,
1292 TechProfileId: flowContext.tpID,
1293 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1294 PbitToGemport: flowContext.pbitToGem,
1295 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001296 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001297
David K. Bainbridge794735f2020-02-11 21:01:37 -08001298 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001299 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 -08001300 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001301
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001302 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1303 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 +05301304 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 +00001305 }
1306
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001308}
1309
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001310// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001311func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1312 intfID := flowContext.intfID
1313 onuID := flowContext.onuID
1314 uniID := flowContext.uniID
1315 portNo := flowContext.portNo
1316 allocID := flowContext.allocID
1317 gemPortID := flowContext.gemPortID
1318 logicalFlow := flowContext.logicalFlow
1319 classifier := flowContext.classifier
1320 action := flowContext.action
1321
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001322 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301323 log.Fields{
1324 "intf-id": intfID,
1325 "onu-id": onuID,
1326 "port-no": portNo,
1327 "alloc-id": allocID,
1328 "gemport-id": gemPortID,
1329 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001330 "flow": logicalFlow,
1331 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301332
1333 uplinkClassifier := make(map[string]interface{})
1334 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301335
manikkaraj kbf256be2019-03-25 00:13:48 +05301336 // Fill Classfier
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001337 uplinkClassifier[EthType] = uint32(ethType)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001338 uplinkClassifier[PacketTagType] = SingleTag
1339 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001340 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301341 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001342 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001343 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001344 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301345 "device-id": f.deviceHandler.device.Id,
1346 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001347 "intf-id": intfID,
1348 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001349 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301350 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 //Add Uplink EthType Flow
1352 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301353 log.Fields{
1354 "ul_classifier": uplinkClassifier,
1355 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001356 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301357 "device-id": f.deviceHandler.device.Id,
1358 "intf-id": intfID,
1359 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301360
David K. Bainbridge794735f2020-02-11 21:01:37 -08001361 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1362 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301363 return olterrors.NewErrInvalidValue(log.Fields{
1364 "classifier": uplinkClassifier,
1365 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301366 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001367 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301368 log.Fields{
1369 "classifier": *classifierProto,
1370 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001371 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001372 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301373 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "action": *actionProto,
1378 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301380 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301381 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001382 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301383 "action": action,
1384 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301386 }
1387
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001389 OnuId: int32(onuID),
1390 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001391 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001392 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001393 AllocId: int32(allocID),
1394 NetworkIntfId: int32(networkIntfID),
1395 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 Classifier: classifierProto,
1397 Action: actionProto,
1398 Priority: int32(logicalFlow.Priority),
1399 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001400 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001401 TechProfileId: flowContext.tpID,
1402 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1403 PbitToGemport: flowContext.pbitToGem,
1404 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001405 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001406 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001407 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001409 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301410 log.Fields{
1411 "device-id": f.deviceHandler.device.Id,
1412 "onu-id": onuID,
1413 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001414 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301415 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001416 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1417 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 +05301418 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1419 log.Fields{
1420 "flow": upstreamFlow,
1421 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301422 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301424}
1425
David K. Bainbridge794735f2020-02-11 21:01:37 -08001426func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001428
1429 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1430 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1431 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001432 if vlanID != ReservedVlan {
1433 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001434 classifier.OVid = vid
1435 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301436 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001437 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1438 vid := uint32(metadata)
1439 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001440 classifier.IVid = vid
1441 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301442 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301443 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001444 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301445 classifier.OPbits = vlanPcp
1446 } else {
1447 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001449 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1450 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1451 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1452 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001453 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001454 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1455 classifier.PktTagType = pktTagType
1456
1457 switch pktTagType {
1458 case SingleTag:
1459 case DoubleTag:
1460 case Untagged:
1461 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001462 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301463 }
1464 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001465 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301466}
1467
Gamze Abaka724d0852020-03-18 12:10:24 +00001468func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001469 var actionCmd openoltpb2.ActionCmd
1470 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301471 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001472 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301473 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001474 if _, ok := actionInfo[VlanPcp]; ok {
1475 action.Cmd.RemarkInnerPbits = true
1476 action.IPbits = actionInfo[VlanPcp].(uint32)
1477 if _, ok := actionInfo[VlanVid]; ok {
1478 action.Cmd.TranslateInnerTag = true
1479 action.IVid = actionInfo[VlanVid].(uint32)
1480 }
1481 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001482 } else if _, ok := actionInfo[PushVlan]; ok {
1483 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301484 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001485 if _, ok := actionInfo[VlanPcp]; ok {
1486 action.OPbits = actionInfo[VlanPcp].(uint32)
1487 action.Cmd.RemarkOuterPbits = true
1488 if _, ok := classifierInfo[VlanVid]; ok {
1489 action.IVid = classifierInfo[VlanVid].(uint32)
1490 action.Cmd.TranslateInnerTag = true
1491 }
1492 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001493 } else if _, ok := actionInfo[TrapToHost]; ok {
1494 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301495 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001496 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301497 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001498 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301499}
1500
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001501// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001502func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1503 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301504}
1505
Gamze Abakafee36392019-10-03 11:17:24 +00001506// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001507func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301508 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001509 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1510
Gamze Abakafee36392019-10-03 11:17:24 +00001511 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301512 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001513 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301514 // return err
1515 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001516 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001517 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001518 }
1519 return nil
1520}
1521
1522// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301523func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001524 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001525 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001526 }
npujarec5762e2020-01-01 14:08:48 +05301527 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301528 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1529 log.Fields{
1530 "tp-id": tpID,
1531 "uni-port-name": uniPortName,
1532 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001533 }
1534 return nil
1535}
1536
David K. Bainbridge794735f2020-02-11 21:01:37 -08001537func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001538
1539 var intfID uint32
1540 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1541 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1542 */
1543 if deviceFlow.AccessIntfId != -1 {
1544 intfID = uint32(deviceFlow.AccessIntfId)
1545 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001546 // We need to log the valid interface ID.
1547 // 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 +00001548 intfID = uint32(deviceFlow.NetworkIntfId)
1549 }
1550
Neha Sharma96b7bf22020-06-15 10:37:32 +00001551 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301552 "flow": *deviceFlow,
1553 "device-id": f.deviceHandler.device.Id,
1554 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001555 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001556
1557 st, _ := status.FromError(err)
1558 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001559 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001560 "err": err,
1561 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301562 "device-id": f.deviceHandler.device.Id,
1563 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001564 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301565 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001566
1567 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001568 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301569 log.Fields{"err": err,
1570 "device-flow": deviceFlow,
1571 "device-id": f.deviceHandler.device.Id,
1572 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001573 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001574 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001575 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301576 log.Fields{
1577 "flow": *deviceFlow,
1578 "device-id": f.deviceHandler.device.Id,
1579 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001580
1581 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1582 if deviceFlow.AccessIntfId != -1 {
1583 // No need to register the flow if it is a trap on nni flow.
1584 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1585 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1586 return err
1587 }
1588 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001590}
1591
Neha Sharma96b7bf22020-06-15 10:37:32 +00001592func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1593 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301594 log.Fields{
1595 "flow": *deviceFlow,
1596 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001597 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001598 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001599 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001600 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301601 log.Fields{
1602 "err": err,
1603 "deviceFlow": deviceFlow,
1604 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001605 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001607 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001608 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001609
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001610 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001611 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001612 "of-flow-id": ofFlowID,
1613 "flow": *deviceFlow,
1614 "device-id": f.deviceHandler.device.Id,
1615 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001616 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301617}
1618
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001620
1621 classifierInfo := make(map[string]interface{})
1622 actionInfo := make(map[string]interface{})
1623
1624 classifierInfo[EthType] = uint32(LldpEthType)
1625 classifierInfo[PacketTagType] = Untagged
1626 actionInfo[TrapToHost] = true
1627
1628 // LLDP flow is installed to trap LLDP packets on the NNI port.
1629 // We manage flow_id resource pool on per PON port basis.
1630 // Since this situation is tricky, as a hack, we pass the NNI port
1631 // index (network_intf_id) as PON port Index for the flow_id resource
1632 // pool. Also, there is no ONU Id available for trapping LLDP packets
1633 // on NNI port, use onu_id as -1 (invalid)
1634 // ****************** CAVEAT *******************
1635 // This logic works if the NNI Port Id falls within the same valid
1636 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1637 // we need to have a re-look at this.
1638 // *********************************************
1639
1640 var onuID = -1
1641 var uniID = -1
1642 var gemPortID = -1
1643
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001645 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301646 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001647 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001648 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001649 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001650 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001651 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001652
David K. Bainbridge794735f2020-02-11 21:01:37 -08001653 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1654 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301655 return olterrors.NewErrInvalidValue(
1656 log.Fields{
1657 "classifier": classifierInfo,
1658 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001659 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001660 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301661 log.Fields{
1662 "classifier": *classifierProto,
1663 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001664 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301666 return olterrors.NewErrInvalidValue(
1667 log.Fields{
1668 "action": actionInfo,
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.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "action": *actionProto,
1674 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001675
1676 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1677 OnuId: int32(onuID), // OnuId not required
1678 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001679 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001680 FlowType: Downstream,
1681 NetworkIntfId: int32(networkInterfaceID),
1682 GemportId: int32(gemPortID),
1683 Classifier: classifierProto,
1684 Action: actionProto,
1685 Priority: int32(flow.Priority),
1686 Cookie: flow.Cookie,
1687 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001689 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301690 log.Fields{
1691 "flow": downstreamflow,
1692 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001693 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301695 log.Fields{
1696 "device-id": f.deviceHandler.device.Id,
1697 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001698 "flow-id": flow.Id})
1699 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1700 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1701 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301702 log.Fields{
1703 "flow": downstreamflow,
1704 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001705 }
1706 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301707}
1708
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001709func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1710 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001711}
1712
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001713//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001715 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1716 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1717 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001718 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301719 log.Fields{
1720 "intf-id": intfID,
1721 "onu-id": onuID,
1722 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001724 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301725 return nil, olterrors.NewErrNotFound("onu-child-device",
1726 log.Fields{
1727 "onu-id": onuID,
1728 "intf-id": intfID,
1729 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001730 }
1731 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1732 //better to ad the device to cache here.
1733 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1734 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301736 log.Fields{
1737 "intf-id": intfID,
1738 "onu-id": onuID,
1739 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001740 }
1741
1742 return onuDev.(*OnuDevice), nil
1743}
1744
1745//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001746func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1747 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301748 log.Fields{
1749 "pon-port": intfID,
1750 "onu-id": onuID,
1751 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001752 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001753 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001754 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301755 return nil, olterrors.NewErrNotFound("onu",
1756 log.Fields{
1757 "interface-id": parentPortNo,
1758 "onu-id": onuID,
1759 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001760 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301761 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001762 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301763 log.Fields{
1764 "device-id": f.deviceHandler.device.Id,
1765 "child_device_id": onuDevice.Id,
1766 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301767 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301768}
1769
Neha Sharma96b7bf22020-06-15 10:37:32 +00001770func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1771 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301772 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001773 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301774 log.Fields{
1775 "intf-id": intfID,
1776 "onu-id": onuID,
1777 "uni-id": uniID,
1778 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001779 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301780 }
1781
1782 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301784 log.Fields{
1785 "msg": *delGemPortMsg,
1786 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001787 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301788 delGemPortMsg,
1789 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001790 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001791 onuDev.deviceType,
1792 onuDev.deviceID,
1793 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301794 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1795 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001796 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301797 "to-adapter": onuDev.deviceType,
1798 "onu-id": onuDev.deviceID,
1799 "proxyDeviceID": onuDev.proxyDeviceID,
1800 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301801 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301803 log.Fields{
1804 "msg": delGemPortMsg,
1805 "from-adapter": f.deviceHandler.device.Type,
1806 "to-adapter": onuDev.deviceType,
1807 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301808 return nil
1809}
1810
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1812 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301813 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301815 log.Fields{
1816 "intf-id": intfID,
1817 "onu-id": onuID,
1818 "uni-id": uniID,
1819 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001820 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301821 }
1822
1823 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001824 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301825 log.Fields{
1826 "msg": *delTcontMsg,
1827 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001828 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301829 delTcontMsg,
1830 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001831 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001832 onuDev.deviceType,
1833 onuDev.deviceID,
1834 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301835 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1836 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001837 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301838 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1839 "proxyDeviceID": onuDev.proxyDeviceID,
1840 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301841 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001842 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301843 log.Fields{
1844 "msg": delTcontMsg,
1845 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301846 return nil
1847}
1848
Girish Gowdrac3037402020-01-22 20:29:53 +05301849// Once the gemport is released for a given onu, it also has to be cleared from local cache
1850// which was used for deriving the gemport->logicalPortNo during packet-in.
1851// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1852// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001853func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001854
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001855 f.onuGemInfoLock.Lock()
1856 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301859 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001860 "gem-port-id": gemPortID,
1861 "intf-id": intfID,
1862 "onu-id": onuID,
1863 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001864 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001865
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001866 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001867deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001868 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301869 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001870 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301871 // If the gemport is found, delete it from local cache.
1872 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001873 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1874 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301876 log.Fields{
1877 "intf-id": intfID,
1878 "onu-id": onuID,
1879 "deletedgemport-id": gemPortID,
1880 "gemports": onu.GemPorts,
1881 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001882 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301883 }
1884 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001885 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301886 }
1887 }
1888}
1889
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301890//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001891// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301892func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001893 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001894
Neha Sharma96b7bf22020-06-15 10:37:32 +00001895 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001896 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301897 return olterrors.NewErrNotFound("tp-id",
1898 log.Fields{
1899 "flow": flow,
1900 "intf": Intf,
1901 "onu-id": onuID,
1902 "uni-id": uniID,
1903 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001904 }
Gamze Abakafee36392019-10-03 11:17:24 +00001905
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001906 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1907 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1908 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1909 log.Fields{
1910 "tpPath": tpPath,
1911 "device-id": f.deviceHandler.device.Id})
1912 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1913 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1914 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1915 log.Fields{
1916 "tp-id": tpID,
1917 "path": tpPath}, err)
1918 }
1919
1920 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1921
1922 if used {
1923 f.flowsUsedByGemPortKey.Lock()
1924 defer f.flowsUsedByGemPortKey.Unlock()
1925
1926 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1927 for i, flowIDinMap := range flowIDs {
1928 if flowIDinMap == flowID {
1929 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1930 // everytime flowsUsedByGemPort cache is updated the same should be updated
1931 // in kv store by calling UpdateFlowIDsForGem
1932 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1933 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1934 return err
1935 }
1936 break
1937 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001938 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001939 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1940 log.Fields{
1941 "gemport-id": gemPortID,
1942 "usedByFlows": flowIDs,
1943 "device-id": f.deviceHandler.device.Id})
1944 return nil
1945 }
1946 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1947 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1948 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1949 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1950 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Esin Karamandf392e12020-12-16 13:33:09 +00001951 // also clear gem to uni cache
1952 f.removeFromGemToUniMap(gemPortKey{
1953 intfID: Intf,
1954 gemPort: uint32(gemPortID),
1955 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001956 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001957
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001958 f.onuIdsLock.Lock() // TODO: What is this lock?
1959
1960 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1961 // by calling DeleteFlowIDsForGem
1962 f.flowsUsedByGemPortKey.Lock()
1963 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1964 f.flowsUsedByGemPortKey.Unlock()
1965 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1966 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1967
1968 f.onuIdsLock.Unlock()
1969
1970 // Delete the gem port on the ONU.
1971 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1972 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1973 log.Fields{
1974 "err": err,
1975 "intf": Intf,
1976 "onu-id": onuID,
1977 "uni-id": uniID,
1978 "device-id": f.deviceHandler.device.Id,
1979 "gemport-id": gemPortID})
1980 }
1981 switch techprofileInst := techprofileInst.(type) {
1982 case *tp.TechProfile:
1983 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1984 if !ok {
1985 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1986 logger.Warn(ctx, err)
1987 }
1988 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1989 logger.Warn(ctx, err)
1990 }
1991 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
1992 logger.Warn(ctx, err)
1993 }
1994 if err := f.RemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}); err != nil {
1995 logger.Warn(ctx, err)
1996 }
1997 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1998 // Delete the TCONT on the ONU.
1999 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
2000 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
2001 log.Fields{
2002 "intf": Intf,
2003 "onu-id": onuID,
2004 "uni-id": uniID,
2005 "device-id": f.deviceHandler.device.Id,
2006 "alloc-id": techprofileInst.UsScheduler.AllocID})
2007 }
2008 }
2009 case *tp.EponProfile:
2010 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
2011 logger.Warn(ctx, err)
2012 }
2013 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2014 logger.Warn(ctx, err)
2015 }
2016 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
2017 // Delete the TCONT on the ONU.
2018 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
2019 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302020 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002021 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302022 "onu-id": onuID,
2023 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002024 "device-id": f.deviceHandler.device.Id,
2025 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00002026 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 default:
2028 logger.Errorw(ctx, "error-unknown-tech",
2029 log.Fields{
2030 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002031 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302033 return nil
2034}
2035
David K. Bainbridge794735f2020-02-11 21:01:37 -08002036// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002037func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00002039 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302040 log.Fields{
2041 "flowDirection": flowDirection,
2042 "flow": *flow,
2043 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002044
2045 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002046 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002047 }
2048
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302049 classifierInfo := make(map[string]interface{})
2050
Neha Sharma96b7bf22020-06-15 10:37:32 +00002051 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302052 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002053 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002054 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302055 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302056
David K. Bainbridge794735f2020-02-11 21:01:37 -08002057 onuID := int32(onu)
2058 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302059
2060 for _, field := range flows.GetOfbFields(flow) {
2061 if field.Type == flows.IP_PROTO {
2062 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002063 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302064 }
2065 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002066 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302067 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002068 "flow-id": flow.Id,
2069 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302070 "onu-id": onuID,
2071 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302072
2073 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2074 onuID = -1
2075 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002076 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2077 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002078 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002079 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080 log.Fields{
2081 "port-number": inPort,
2082 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002083 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002084 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302085 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2087 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})
2088 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2089 }
2090 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2091 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2092 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2093 return err
2094 }
2095 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2096 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2097 return err
2098 }
2099 if !flowInfo.Flow.ReplicateFlow {
2100 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002101 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002102 "flow-id": flow.Id,
2103 "stored-flow": flowInfo.Flow,
2104 "device-id": f.deviceHandler.device.Id,
2105 "stored-flow-id": flowInfo.Flow.FlowId,
2106 "onu-id": onuID,
2107 "intf": Intf,
2108 })
2109 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302110 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002111 } else {
2112 gems := make([]uint32, 0)
2113 for _, gem := range flowInfo.Flow.PbitToGemport {
2114 gems = appendUnique32bit(gems, gem)
2115 }
2116 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2117 for _, gem := range gems {
2118 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002119 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002120 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002121 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002122 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002123 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002124 "onu-id": onuID,
2125 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002126 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002127 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002128 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302129 }
2130 }
2131 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002132
2133 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2134 if isDatapathFlow(flow) {
2135 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2136 var inverseDirection string
2137 if flowDirection == Upstream {
2138 inverseDirection = Downstream
2139 } else {
2140 inverseDirection = Upstream
2141 }
2142
2143 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002144 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002145 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002146 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002147 }
2148 }
2149 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002150}
2151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002152//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002153func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002154
Neha Sharma96b7bf22020-06-15 10:37:32 +00002155 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302156 var direction string
2157 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002158
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302159 for _, action := range flows.GetActions(flow) {
2160 if action.Type == flows.OUTPUT {
2161 if out := action.GetOutput(); out != nil {
2162 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302164 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002166 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002167 }
2168 }
2169 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002170
2171 if flows.HasGroup(flow) {
2172 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002173 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002174 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302175 direction = Upstream
2176 } else {
2177 direction = Downstream
2178 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302179
Girish Gowdracefae192020-03-19 18:14:10 -07002180 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002181 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002182
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002183 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002184}
2185
Esin Karamanae41e2b2019-12-17 18:13:13 +00002186//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2187func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2188 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2189 if ethType, ok := classifierInfo[EthType]; ok {
2190 if ethType.(uint32) == IPv4EthType {
2191 if ipProto, ok := classifierInfo[IPProto]; ok {
2192 if ipProto.(uint32) == IgmpProto {
2193 return true
2194 }
2195 }
2196 }
2197 }
2198 }
2199 return false
2200}
2201
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002202// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2203func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2204 // Step1 : Fill flowControlBlock
2205 // Step2 : Push the flowControlBlock to ONU channel
2206 // Step3 : Wait on response channel for response
2207 // Step4 : Return error value
2208 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2209 errChan := make(chan error)
2210 flowCb := flowControlBlock{
2211 ctx: ctx,
2212 addFlow: addFlow,
2213 flow: flow,
2214 flowMetadata: flowMetadata,
2215 errChan: &errChan,
2216 }
2217 inPort, outPort := getPorts(flow)
2218 var onuID uint32
2219 if inPort != InvalidPort && outPort != InvalidPort {
2220 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2221 }
2222 // inPort or outPort is InvalidPort for trap-from-nni flows.
2223 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2224 // Send the flowCb on the ONU flow channel
2225 f.incomingFlows[onuID] <- flowCb
2226 // Wait on the channel for flow handlers return value
2227 err := <-errChan
2228 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2229 return err
2230}
2231
2232// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2233// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2234func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2235 for {
2236 // block on the channel to receive an incoming flow
2237 // process the flow completely before proceeding to handle the next flow
2238 flowCb := <-subscriberFlowChannel
2239 if flowCb.addFlow {
2240 logger.Debugw(flowCb.ctx, "adding-flow",
2241 log.Fields{"device-id": f.deviceHandler.device.Id,
2242 "flowToAdd": flowCb.flow})
2243 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2244 // Pass the return value over the return channel
2245 *flowCb.errChan <- err
2246 } else {
2247 logger.Debugw(flowCb.ctx, "removing-flow",
2248 log.Fields{"device-id": f.deviceHandler.device.Id,
2249 "flowToRemove": flowCb.flow})
2250 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2251 // Pass the return value over the return channel
2252 *flowCb.errChan <- err
2253 }
2254 }
2255}
2256
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002257// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302258// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002259func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002260 classifierInfo := make(map[string]interface{})
2261 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002262 var UsMeterID uint32
2263 var DsMeterID uint32
2264
Neha Sharma96b7bf22020-06-15 10:37:32 +00002265 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302266 log.Fields{
2267 "flow": flow,
2268 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002269 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002270
Neha Sharma96b7bf22020-06-15 10:37:32 +00002271 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002272 if err != nil {
2273 // Error logging is already done in the called function
2274 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002275 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302276 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002277
Esin Karamanccb714b2019-11-29 15:02:06 +00002278 if flows.HasGroup(flow) {
2279 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002280 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002281 }
2282
manikkaraj k17652a72019-05-06 09:06:36 -04002283 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002284 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002285 if err != nil {
2286 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002287 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002288 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002289
Neha Sharma96b7bf22020-06-15 10:37:32 +00002290 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302291 log.Fields{
2292 "classifierinfo_inport": classifierInfo[InPort],
2293 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002294 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002295
Humera Kouser94d7a842019-08-25 19:04:32 -04002296 if ethType, ok := classifierInfo[EthType]; ok {
2297 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002298 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002299 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002300 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002301 if ethType.(uint32) == PPPoEDEthType {
2302 if voltha.Port_ETHERNET_NNI == IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
2303 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2304 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2305 }
2306 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002307 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002308 if ipProto, ok := classifierInfo[IPProto]; ok {
2309 if ipProto.(uint32) == IPProtoDhcp {
2310 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302311 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002313 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002314 }
2315 }
2316 }
2317 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002318 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002319 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002320 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002321 }
A R Karthick1f85b802019-10-11 05:06:05 +00002322
npujarec5762e2020-01-01 14:08:48 +05302323 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002324
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002326 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302327 return olterrors.NewErrNotFound("tpid-for-flow",
2328 log.Fields{
2329 "flow": flow,
2330 "intf-id": IntfID,
2331 "onu-id": onuID,
2332 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002333 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002334 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302335 log.Fields{
2336 "tp-id": TpID,
2337 "intf-id": intfID,
2338 "onu-id": onuID,
2339 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002340 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002341 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002342 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002343 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002344 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002346
2347 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002348 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002349}
Girish Gowdra3d633032019-12-10 16:37:05 +05302350
Esin Karamanccb714b2019-11-29 15:02:06 +00002351// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002352func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002353 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302355 "classifier-info": classifierInfo,
2356 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002357
Esin Karaman65409d82020-03-18 10:58:18 +00002358 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002359 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002360 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002362
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002363 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364
David K. Bainbridge794735f2020-02-11 21:01:37 -08002365 onuID := NoneOnuID
2366 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002367
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002368 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002369 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002370 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002371 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002372 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2373 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002374 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002375 }
2376 groupID := actionInfo[GroupID].(uint32)
2377 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002378 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002379 FlowType: Multicast,
2380 NetworkIntfId: int32(networkInterfaceID),
2381 GroupId: groupID,
2382 Classifier: classifierProto,
2383 Priority: int32(flow.Priority),
2384 Cookie: flow.Cookie}
2385
Kent Hagermane6ff1012020-07-14 15:07:53 -04002386 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002387 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002388 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002390 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002391 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002392 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002393 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002394 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002395 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002396 //cached group can be removed now
2397 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2398 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2399 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002400 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002401
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002402 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2403 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2404 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002405 }
2406 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002407}
2408
Esin Karaman65409d82020-03-18 10:58:18 +00002409//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2410func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2411 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002413 if err != nil {
2414 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2415 }
2416 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002417 }
Esin Karaman65409d82020-03-18 10:58:18 +00002418 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302419 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002420 if e == nil && len(nniPorts) > 0 {
2421 return nniPorts[0], nil
2422 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302423 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002424}
2425
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002426//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002428
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302430 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002431 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302432 log.Fields{
2433 "intf-id": intfID,
2434 "onu-id": onuID,
2435 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002436 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302437 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002438 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002439
Neha Sharma96b7bf22020-06-15 10:37:32 +00002440 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002441 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002443 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002444 tpDownloadMsg,
2445 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002446 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002447 onuDev.deviceType,
2448 onuDev.deviceID,
2449 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002450 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302451 return olterrors.NewErrCommunication("send-techprofile-download-request",
2452 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002453 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302454 "to-adapter": onuDev.deviceType,
2455 "onu-id": onuDev.deviceID,
2456 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002457 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002458 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302459 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302460}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002461
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302462//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002463func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302464
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002465 f.onuGemInfoLock.Lock()
2466 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002467 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002468 // If the ONU already exists in onuGemInfo list, nothing to do
2469 for _, onu := range onugem {
2470 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2471 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2472 log.Fields{"onuID": onuID,
2473 "serialNum": serialNum})
2474 return nil
2475 }
2476 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002477
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302478 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002479 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002480 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002481 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302484 log.Fields{
2485 "intf-id": intfID,
2486 "onu-id": onuID,
2487 "serial-num": serialNum,
2488 "onu": onu,
2489 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002490 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002491}
2492
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302493//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302494func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002495
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002496 f.onuGemInfoLock.Lock()
2497 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002498
Neha Sharma96b7bf22020-06-15 10:37:32 +00002499 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302500 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002501 "gem-port-id": gemPort,
2502 "intf-id": intfID,
2503 "onu-id": onuID,
2504 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002505 "onu-gem": f.onuGemInfo})
2506 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302507 // update the gem to the local cache as well as to kv strore
2508 for idx, onu := range onugem {
2509 if onu.OnuID == onuID {
2510 // check if gem already exists , else update the cache and kvstore
2511 for _, gem := range onu.GemPorts {
2512 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002513 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302514 log.Fields{
2515 "gem": gemPort,
2516 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302517 return
2518 }
2519 }
2520 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002521 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002522 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302523 }
2524 }
npujarec5762e2020-01-01 14:08:48 +05302525 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302526 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002527 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302528 log.Fields{
2529 "intf-id": intfID,
2530 "onu-id": onuID,
2531 "gemPort": gemPort,
2532 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002533 return
2534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302536 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002537 "gem-port-id": gemPort,
2538 "intf-id": intfID,
2539 "onu-id": onuID,
2540 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002541 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002542}
2543
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002544//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302545func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002547 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 var err error
2549
2550 if packetIn.IntfType == "pon" {
2551 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002552 // get onu and uni ids associated with the given pon and gem ports
2553 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002554 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002555 return logicalPortNum, err
2556 }
Esin Karamandf392e12020-12-16 13:33:09 +00002557 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2558
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002559 if packetIn.PortNo != 0 {
2560 logicalPortNum = packetIn.PortNo
2561 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002562 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002563 }
2564 // 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 +00002565 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002566 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002567 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002568 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002569
2570 if logger.V(log.DebugLevel) {
2571 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2572 log.Fields{
2573 "logical-port-num": logicalPortNum,
2574 "intf-type": packetIn.IntfType,
2575 "packet": hex.EncodeToString(packetIn.Pkt),
2576 })
2577 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002578 return logicalPortNum, nil
2579}
2580
Esin Karamandf392e12020-12-16 13:33:09 +00002581//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2582func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2583 key := gemPortKey{
2584 intfID: intfID,
2585 gemPort: gemPortID,
2586 }
2587 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2588 if ok {
2589 if len(uniPortInfo) > 1 {
2590 //return onu ID and uni port from the cache
2591 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2592 log.Fields{
2593 "intfID": intfID,
2594 "gemPortID": gemPortID,
2595 "onuID, uniID": uniPortInfo})
2596 return uniPortInfo[0], uniPortInfo[1], nil
2597 }
2598 }
2599 //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.
2600 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2601 if err == nil {
2602 f.toGemToUniMap(ctx, key, onuID, uniID)
2603 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2604 log.Fields{
2605 "gemPortKey": key,
2606 "onuID": onuID,
2607 "uniID": uniID})
2608 return onuID, uniID, nil
2609 }
2610 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2611 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2612 errors.New("no uni port found"))
2613}
2614
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002615//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002616func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002617 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002618
2619 ctag, priority, err := getCTagFromPacket(ctx, packet)
2620 if err != nil {
2621 return 0, err
2622 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302623
Esin Karaman7fb80c22020-07-16 14:23:33 +00002624 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002625 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002626 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002627 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002628 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302629 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302631 log.Fields{
2632 "pktinkey": pktInkey,
2633 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002634
2635 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002636 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 //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 +00002638 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302639 if err == nil {
2640 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002641 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302642 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002643 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002644 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302645 log.Fields{
2646 "pktinkey": pktInkey,
2647 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302648 return gemPortID, nil
2649 }
2650 }
Shrey Baid26912972020-04-16 21:02:31 +05302651 return uint32(0), olterrors.NewErrNotFound("gem-port",
2652 log.Fields{
2653 "pktinkey": pktInkey,
2654 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002655
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656}
2657
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002658func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2659 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002660 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002661 classifier[PacketTagType] = DoubleTag
2662 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002663 /* We manage flowId resource pool on per PON port basis.
2664 Since this situation is tricky, as a hack, we pass the NNI port
2665 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002666 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002667 on NNI port, use onu_id as -1 (invalid)
2668 ****************** CAVEAT *******************
2669 This logic works if the NNI Port Id falls within the same valid
2670 range of PON Port Ids. If this doesn't work for some OLT Vendor
2671 we need to have a re-look at this.
2672 *********************************************
2673 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002674 onuID := -1
2675 uniID := -1
2676 gemPortID := -1
2677 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002678 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302679 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302680 return olterrors.NewErrNotFound("nni-intreface-id",
2681 log.Fields{
2682 "classifier": classifier,
2683 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002684 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302685 }
2686
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002687 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002688 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002691
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002692 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2693 log.Fields{
2694 "classifier": classifier,
2695 "action": action,
2696 "flowId": logicalFlow.Id,
2697 "intf-id": networkInterfaceID})
2698
David K. Bainbridge794735f2020-02-11 21:01:37 -08002699 classifierProto, err := makeOpenOltClassifierField(classifier)
2700 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002701 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002704 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002705 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002706 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002707 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002708 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002709 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2710 OnuId: int32(onuID), // OnuId not required
2711 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002712 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002713 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002714 AllocId: int32(allocID), // AllocId not used
2715 NetworkIntfId: int32(networkInterfaceID),
2716 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002717 Classifier: classifierProto,
2718 Action: actionProto,
2719 Priority: int32(logicalFlow.Priority),
2720 Cookie: logicalFlow.Cookie,
2721 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002722 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002723 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002724 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002725 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002726 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2727 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2728 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002729 }
2730 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002731}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002732
Esin Karamanae41e2b2019-12-17 18:13:13 +00002733//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2734func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2735 var packetType string
2736 ovid, ivid := false, false
2737 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2738 vid := vlanID & VlanvIDMask
2739 if vid != ReservedVlan {
2740 ovid = true
2741 }
2742 }
2743 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2744 vid := uint32(metadata)
2745 if vid != ReservedVlan {
2746 ivid = true
2747 }
2748 }
2749 if ovid && ivid {
2750 packetType = DoubleTag
2751 } else if !ovid && !ivid {
2752 packetType = Untagged
2753 } else {
2754 packetType = SingleTag
2755 }
2756 return packetType
2757}
2758
2759//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002760func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002761 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002762 action := make(map[string]interface{})
2763 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2764 action[TrapToHost] = true
2765 /* We manage flowId resource pool on per PON port basis.
2766 Since this situation is tricky, as a hack, we pass the NNI port
2767 index (network_intf_id) as PON port Index for the flowId resource
2768 pool. Also, there is no ONU Id available for trapping packets
2769 on NNI port, use onu_id as -1 (invalid)
2770 ****************** CAVEAT *******************
2771 This logic works if the NNI Port Id falls within the same valid
2772 range of PON Port Ids. If this doesn't work for some OLT Vendor
2773 we need to have a re-look at this.
2774 *********************************************
2775 */
2776 onuID := -1
2777 uniID := -1
2778 gemPortID := -1
2779 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002780 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002781 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302782 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002783 "classifier": classifier,
2784 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002785 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002786 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002787 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002788 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002789 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002790 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002791
David K. Bainbridge794735f2020-02-11 21:01:37 -08002792 classifierProto, err := makeOpenOltClassifierField(classifier)
2793 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002794 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002795 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002796 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002797 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002798 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002799 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002800 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002801 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002802 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2803 OnuId: int32(onuID), // OnuId not required
2804 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002805 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 FlowType: Downstream,
2807 AllocId: int32(allocID), // AllocId not used
2808 NetworkIntfId: int32(networkInterfaceID),
2809 GemportId: int32(gemPortID), // GemportId not used
2810 Classifier: classifierProto,
2811 Action: actionProto,
2812 Priority: int32(logicalFlow.Priority),
2813 Cookie: logicalFlow.Cookie,
2814 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002815 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002816 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002817 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002818 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002819 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2820 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2821 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002822 }
2823 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002824}
2825
salmansiddiqui7ac62132019-08-22 03:58:50 +00002826func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2827 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302828 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002829 }
2830 if Dir == tp_pb.Direction_UPSTREAM {
2831 return "upstream", nil
2832 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2833 return "downstream", nil
2834 }
2835 return "", nil
2836}
2837
Kent Hagermane6ff1012020-07-14 15:07:53 -04002838// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302839func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002840 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002841 tpID uint32, uni string) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002842 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002843 intfID := args[IntfID]
2844 onuID := args[OnuID]
2845 uniID := args[UniID]
2846 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002847 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002849 gemToAes := make(map[uint32]bool)
2850
2851 var attributes []tp.IGemPortAttribute
2852 var direction = tp_pb.Direction_UPSTREAM
2853 switch TpInst := TpInst.(type) {
2854 case *tp.TechProfile:
2855 if IsUpstream(actionInfo[Output].(uint32)) {
2856 attributes = TpInst.UpstreamGemPortAttributeList
2857 } else {
2858 attributes = TpInst.DownstreamGemPortAttributeList
2859 direction = tp_pb.Direction_DOWNSTREAM
2860 }
2861 default:
2862 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2863 return
2864 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002865
2866 if len(gemPorts) == 1 {
2867 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002868 gemPortID = gemPorts[0]
2869 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002870 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2871 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 pBitMap := attributes[idx].PbitMap
2873 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2874 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2875 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2876 // this pcp bit traffic.
2877 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2878 if pbitSet == pbit1 {
2879 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2880 pbitToGem[pcp] = gemID
2881 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002882 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002883 }
2884 }
2885 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 if gem := f.techprofile[intfID].GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2887 gemPortID = gem.(tp.IGemPortAttribute).GemportID
2888 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(tp.IGemPortAttribute).AesEncryption)
2889 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002890 }
2891
Gamze Abaka7650be62021-02-26 10:50:36 +00002892 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2893 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2894
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 if ipProto, ok := classifierInfo[IPProto]; ok {
2896 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002898 "tp-id": tpID,
2899 "alloc-id": allocID,
2900 "intf-id": intfID,
2901 "onu-id": onuID,
2902 "uni-id": uniID,
2903 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002904 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002905 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002906 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 }
2908
Girish Gowdra32625212020-04-29 11:26:35 -07002909 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002910 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302911 log.Fields{
2912 "intf-id": intfID,
2913 "onu-id": onuID,
2914 "uni-id": uniID,
2915 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002916 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002917 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002918 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002921 return
2922 }
2923 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002924 if ethType.(uint32) == EapEthType {
2925 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002926 "intf-id": intfID,
2927 "onu-id": onuID,
2928 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002929 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002930 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002931 var vlanID uint32
2932 if val, ok := classifierInfo[VlanVid]; ok {
2933 vlanID = (val.(uint32)) & VlanvIDMask
2934 } else {
2935 vlanID = DefaultMgmtVlan
2936 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002937 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002938 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002939 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002940 } else if ethType.(uint32) == PPPoEDEthType {
2941 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2942 "tp-id": tpID,
2943 "alloc-id": allocID,
2944 "intf-id": intfID,
2945 "onu-id": onuID,
2946 "uni-id": uniID,
2947 })
2948 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002950 logger.Warn(ctx, err)
2951 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002952 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002953 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002954 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002955 "intf-id": intfID,
2956 "onu-id": onuID,
2957 "uni-id": uniID,
2958 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002959 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002960 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002961 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002962 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002963 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002964 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002965 "intf-id": intfID,
2966 "onu-id": onuID,
2967 "uni-id": uniID,
2968 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002969 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002970 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002971 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 }
2973 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302975 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002976 "intf-id": intfID,
2977 "onu-id": onuID,
2978 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302979 "classifier": classifierInfo,
2980 "action": actionInfo,
2981 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 return
2983 }
2984 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002985 go func() {
2986 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2987 logger.Warn(ctx, err)
2988 }
2989 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002990}
2991
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002992func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2993 f.flowsUsedByGemPortKey.RLock()
2994 flowIDList := f.flowsUsedByGemPort[gemPortID]
2995 f.flowsUsedByGemPortKey.RUnlock()
2996 return len(flowIDList) > 1
2997
Gamze Abakafee36392019-10-03 11:17:24 +00002998}
2999
npujarec5762e2020-01-01 14:08:48 +05303000func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
3001 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00003002 tpGemPorts := tpInst.UpstreamGemPortAttributeList
3003 for _, currentGemPort := range currentGemPorts {
3004 for _, tpGemPort := range tpGemPorts {
3005 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
3006 return true, currentGemPort
3007 }
3008 }
3009 }
Girish Gowdra54934262019-11-13 14:19:55 +05303010 if tpInst.InstanceCtrl.Onu == "single-instance" {
3011 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003012 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003013 logger.Warn(ctx, err)
3014 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003015 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003016 logger.Warn(ctx, err)
3017 }
Girish Gowdra54934262019-11-13 14:19:55 +05303018
3019 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
3020 // still be used on other uni ports.
3021 // So, we need to check and make sure that no other gem port is referring to the given TP ID
3022 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07003023 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05303025 for i := 0; i < len(tpInstances); i++ {
3026 tpI := tpInstances[i]
3027 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05303028 for _, tpGemPort := range tpGemPorts {
3029 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05303031 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05303032 }
3033 }
3034 }
3035 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00003037 return false, 0
3038}
3039
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003041 for _, field := range flows.GetOfbFields(flow) {
3042 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003045 } else if field.Type == flows.ETH_DST {
3046 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003054 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05303055 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003060 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003063 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003066 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003067 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003069 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003072 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003073 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003075 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 return
3081 }
3082 }
3083}
3084
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003086 for _, action := range flows.GetActions(flow) {
3087 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003089 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003092 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 }
Scott Baker355d1742019-10-24 10:57:52 -07003094 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003096 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003097 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 if out := action.GetPush(); out != nil {
3099 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 } else {
3102 actionInfo[PushVlan] = true
3103 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003104 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303105 log.Fields{
3106 "push-tpid": actionInfo[TPID].(uint32),
3107 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 }
3109 }
Scott Baker355d1742019-10-24 10:57:52 -07003110 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 if out := action.GetSetField(); out != nil {
3112 if field := out.GetField(); field != nil {
3113 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003114 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003116 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3117 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 }
3119 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003122 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003123 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 }
3125 }
3126 return nil
3127}
3128
Neha Sharma96b7bf22020-06-15 10:37:32 +00003129func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003130 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003131 fieldtype := ofbField.GetType()
3132 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003133 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3134 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003136 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003138 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003139 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3140 pcp := ofbField.GetVlanPcp()
3141 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003142 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003143 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003145 }
3146 }
3147}
3148
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003150 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003152 } else {
3153 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003155 }
3156}
3157
Neha Sharma96b7bf22020-06-15 10:37:32 +00003158func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003159 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003160 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003161 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3162 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003163 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003164 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303166 log.Fields{
3167 "newinport": classifierInfo[InPort].(uint32),
3168 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003169 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303170 return olterrors.NewErrNotFound("child-in-port",
3171 log.Fields{
3172 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3173 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003174 }
3175 }
3176 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003177 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003178 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003179 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003180 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003181 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003182 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303183 log.Fields{
3184 "newoutport": actionInfo[Output].(uint32),
3185 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003186 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303187 return olterrors.NewErrNotFound("out-port",
3188 log.Fields{
3189 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3190 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003191 }
3192 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3193 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003194 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303197 log.Fields{
3198 "newinport": actionInfo[Output].(uint32),
3199 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303201 return olterrors.NewErrNotFound("nni-port",
3202 log.Fields{
3203 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3204 "in-port": classifierInfo[InPort].(uint32),
3205 "out-port": actionInfo[Output].(uint32),
3206 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003207 }
3208 }
3209 }
3210 return nil
3211}
Gamze Abakafee36392019-10-03 11:17:24 +00003212
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003214 /* Metadata 8 bytes:
3215 Most Significant 2 Bytes = Inner VLAN
3216 Next 2 Bytes = Tech Profile ID(TPID)
3217 Least Significant 4 Bytes = Port ID
3218 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3219 subscriber related flows.
3220 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003221 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003222 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003223 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003224 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003225 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003226 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003227}
3228
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003229func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3230 for _, sliceElement := range slice {
3231 if sliceElement == item {
3232 return slice
3233 }
3234 }
3235 return append(slice, item)
3236}
3237
3238func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003239 for _, sliceElement := range slice {
3240 if sliceElement == item {
3241 return slice
3242 }
3243 }
3244 return append(slice, item)
3245}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303246
3247// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003248func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303249
3250 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3251 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003252 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003253 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003254 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003255 log.Fields{
3256 "port-number": action[Output].(uint32),
3257 "error": err})
3258 return uint32(0), err
3259 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303261 return intfID, nil
3262 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003263 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003264 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003265 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003266 log.Fields{
3267 "port-number": action[Output].(uint32),
3268 "error": err})
3269 return uint32(0), err
3270 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003271 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303272 return intfID, nil
3273 }
3274 return uint32(0), nil
3275}
3276
3277// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003278func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3279 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3280 if err != nil {
3281 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3282 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3283 return
3284 }
3285 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003286
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003287 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003288 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003289 f.packetInGemPortLock.RUnlock()
3290
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303291 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003292 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003293 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 +05303294 log.Fields{
3295 "pktinkey": pktInkey,
3296 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003297 return
3298 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303299 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003300 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003301 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003302 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003303
npujarec5762e2020-01-01 14:08:48 +05303304 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003305 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 +05303306 log.Fields{
3307 "pktinkey": pktInkey,
3308 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303309}
3310
Esin Karaman7fb80c22020-07-16 14:23:33 +00003311//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3312func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3313 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003314 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003315 return 0, 0, errors.New("invalid packet length")
3316 }
3317 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3318 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3319
3320 var index int8
3321 if outerEthType == 0x8100 {
3322 if innerEthType == 0x8100 {
3323 // q-in-q 802.1ad or 802.1q double tagged packet.
3324 // get the inner vlanId
3325 index = 18
3326 } else {
3327 index = 14
3328 }
3329 priority := (packet[index] >> 5) & 0x7
3330 //13 bits composes vlanId value
3331 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3332 return vlan, priority, nil
3333 }
3334 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3335 return 0, 0, nil
3336}
3337
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303338// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303339func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003340
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003341 f.onuGemInfoLock.Lock()
3342 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003343
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003344 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303345 for idx, onu := range onugem {
3346 if onu.OnuID == onuID {
3347 for _, uni := range onu.UniPorts {
3348 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003349 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 +05303350 return
3351 }
3352 }
3353 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003354 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303355 }
3356 }
npujarec5762e2020-01-01 14:08:48 +05303357 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003358
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303359}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303360
npujarec5762e2020-01-01 14:08:48 +05303361func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3362 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303363 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003364 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303365 return
3366 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303368 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003369 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303370 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003371 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303372}
Esin Karamanccb714b2019-11-29 15:02:06 +00003373
Girish Gowdra9602eb42020-09-09 15:50:39 -07003374//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3375// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003376func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003377 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003378 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003379 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3380 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3381
Esin Karamanccb714b2019-11-29 15:02:06 +00003382 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003383 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 -07003384 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003385 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003386
3387 var onuID = int32(NoneOnuID)
3388 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003389 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3390 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3391 log.Fields{
3392 "flow": flow,
3393 "device-id": f.deviceHandler.device.Id,
3394 "intf-id": networkInterfaceID,
3395 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003396 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003397 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3398 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3399 log.Fields{
3400 "flow": flowInfo.Flow,
3401 "flow-id": flow.Id,
3402 "device-id": f.deviceHandler.device.Id})
3403 // Remove from device
3404 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3405 // DKB
3406 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3407 log.Fields{
3408 "flow-id": flow.Id,
3409 "error": err})
3410 return err
3411 }
3412 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003413 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003414}
3415
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003416// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3417func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3418 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3419 if err != nil {
3420 _ = olterrors.NewErrNotFound("onu", log.Fields{
3421 "pon-port": f.ponPortIdx}, err).Log()
3422 return
3423 }
3424
3425 f.subscriberDataPathFlowIDMapLock.Lock()
3426 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3427
3428 for _, onu := range onuGemInfo {
3429 for _, uniID := range onu.UniPorts {
3430 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3431 if err != nil {
3432 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3433 }
3434 for _, flowID := range flowIDs {
3435 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3436 if flowInfo == nil {
3437 // Error is already logged in the called function
3438 continue
3439 }
3440 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3441 flowInfo.Flow.FlowType == Downstream &&
3442 flowInfo.Flow.Classifier.OVid > 0 &&
3443 flowInfo.Flow.TechProfileId > 0 {
3444 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3445 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3446 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3447 }
3448 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3449 flowInfo.Flow.FlowType == Upstream &&
3450 flowInfo.Flow.Action.OVid > 0 &&
3451 flowInfo.Flow.TechProfileId > 0 {
3452 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3453 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3454 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3455 }
3456 }
3457 }
3458 }
3459 }
3460}
3461
3462// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3463func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3464 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3465}