blob: d9ffa7abcd5e8da9420b791c1e3ad7f7933b83cc [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"
serkant.uluderya4aff1862020-09-17 23:35:26 +030025 "strings"
26 "sync"
27
Girish Gowdraa09aeab2020-09-14 16:30:52 -070028 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
29 "github.com/opencord/voltha-lib-go/v4/pkg/log"
30 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070032 "github.com/opencord/voltha-protos/v4/go/common"
33 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
34 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
35 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
36 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
37 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040038
Thomas Lee S94109f12020-03-03 16:39:29 +053039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053042)
43
44const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070045 //IPProtoDhcp flow category
46 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053047
Girish Gowdraa09aeab2020-09-14 16:30:52 -070048 //IgmpProto proto value
49 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050
51 //EapEthType eapethtype value
52 EapEthType = 0x888e
53 //LldpEthType lldp ethtype value
54 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000055 //IPv4EthType IPv4 ethernet type value
56 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057
Andrea Campanella7acc0b92020-02-14 09:20:49 +010058 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
59 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 //DefaultMgmtVlan default vlan value
62 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053063
manikkaraj kbf256be2019-03-25 00:13:48 +053064 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065
David K. Bainbridge82efc492019-09-04 09:57:11 -070066 //Upstream constant
67 Upstream = "upstream"
68 //Downstream constant
69 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000070 //Multicast constant
71 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 //PacketTagType constant
73 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 //Untagged constant
75 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //SingleTag constant
77 SingleTag = "single_tag"
78 //DoubleTag constant
79 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053080
81 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082
83 //EthType constant
84 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000085 //EthDst constant
86 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //TPID constant
88 TPID = "tpid"
89 //IPProto constant
90 IPProto = "ip_proto"
91 //InPort constant
92 InPort = "in_port"
93 //VlanVid constant
94 VlanVid = "vlan_vid"
95 //VlanPcp constant
96 VlanPcp = "vlan_pcp"
97
98 //UDPDst constant
99 UDPDst = "udp_dst"
100 //UDPSrc constant
101 UDPSrc = "udp_src"
102 //Ipv4Dst constant
103 Ipv4Dst = "ipv4_dst"
104 //Ipv4Src constant
105 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700106 //Metadata constant
107 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 //TunnelID constant
109 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Output constant
111 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000112 //GroupID constant
113 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 // Actions
115
116 //PopVlan constant
117 PopVlan = "pop_vlan"
118 //PushVlan constant
119 PushVlan = "push_vlan"
120 //TrapToHost constant
121 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400122 //MaxMeterBand constant
123 MaxMeterBand = 2
124 //VlanPCPMask contant
125 VlanPCPMask = 0xFF
126 //VlanvIDMask constant
127 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000128 //IntfID constant
129 IntfID = "intfId"
130 //OnuID constant
131 OnuID = "onuId"
132 //UniID constant
133 UniID = "uniId"
134 //PortNo constant
135 PortNo = "portNo"
136 //AllocID constant
137 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138
139 //NoneOnuID constant
140 NoneOnuID = -1
141 //NoneUniID constant
142 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700143
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700144 // Max number of flows that can be queued per ONU
145 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530146
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700147 bitMapPrefix = "0b"
148 pbit1 = '1'
149)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400150
Esin Karamandf392e12020-12-16 13:33:09 +0000151type gemPortKey struct {
152 intfID uint32
153 gemPort uint32
154}
155
Gamze Abakafee36392019-10-03 11:17:24 +0000156type schedQueue struct {
157 direction tp_pb.Direction
158 intfID uint32
159 onuID uint32
160 uniID uint32
161 tpID uint32
162 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700163 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000164 meterID uint32
165 flowMetadata *voltha.FlowMetadata
166}
167
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700168// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
169type subscriberDataPathFlowIDKey struct {
170 intfID uint32
171 onuID uint32
172 uniID uint32
173 direction string
174 tpID uint32
175}
176
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700177// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
178// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
179// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
180// flow and processes it serially
181type flowControlBlock struct {
182 ctx context.Context // Flow handler context
183 addFlow bool // if true flow to be added, else removed
184 flow *voltha.OfpFlowStats // Flow message
185 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
186 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000187}
188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700189//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530190type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700191 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
192 techprofile map[uint32]tp.TechProfileIf
193 deviceHandler *DeviceHandler
194 grpMgr *OpenOltGroupMgr
195 resourceMgr *rsrcMgr.OpenOltResourceMgr
196
197 onuIdsLock sync.RWMutex // TODO: Do we need this?
198
199 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
200 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
201
202 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
203 packetInGemPortLock sync.RWMutex
204
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700205 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700206 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700207 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700208 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700210 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
211 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
212 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
213 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700214
215 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
216 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
217 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000218
219 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
220 gemToUniMap map[gemPortKey][]uint32
221 //We need to have a global lock on the gemToUniLock map
222 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530223}
224
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700225//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700226func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000227 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530229 var err error
230 var idx uint32
231
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700233 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000235 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000236 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
237 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530238 return nil
239 }
William Kurkian740a09c2019-10-23 17:07:38 -0400240 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700241 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530242 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700243 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700244 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700245 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
246 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700247
248 // Create a slice of buffered channels for handling concurrent flows per ONU.
249 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
250 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
251 for i := range flowMgr.incomingFlows {
252 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
253 // Spin up a go routine to handling incoming flows (add/remove).
254 // There will be on go routine per ONU.
255 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
256 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
257 }
258
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530259 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700260 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
261 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530262 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700263 //Load flowID list per gem map per interface from the kvstore.
264 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000265 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000266
267 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
268 flowMgr.gemToUniLock = sync.RWMutex{}
269
Girish Gowdra9602eb42020-09-09 15:50:39 -0700270 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700271 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000272 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530273 return &flowMgr
274}
275
Esin Karamandf392e12020-12-16 13:33:09 +0000276// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
277func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
278 f.gemToUniLock.Lock()
279 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
280 f.gemToUniLock.Unlock()
281}
282
283// fromGemToUniMap returns onu and uni ID associated with the given key
284func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
285 f.gemToUniLock.RLock()
286 defer f.gemToUniLock.RUnlock()
287 val, ok := f.gemToUniMap[key]
288 return val, ok
289}
290
291// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
292func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
293 f.gemToUniLock.Lock()
294 defer f.gemToUniLock.Unlock()
295 delete(f.gemToUniMap, key)
296}
297
Kent Hagermane6ff1012020-07-14 15:07:53 -0400298func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700299 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
300 // Flow is not replicated in this case, we need to register the flow for a single gem-port
301 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
302 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
303 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
304 for _, gemPort := range deviceFlow.PbitToGemport {
305 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
306 return err
307 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700308 }
Gamze Abakafee36392019-10-03 11:17:24 +0000309 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700310 return nil
311}
312
313func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
314 f.flowsUsedByGemPortKey.Lock()
315 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
316 if !ok {
317 flowIDList = []uint64{flowFromCore.Id}
318 }
319 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
320 f.flowsUsedByGemPort[gemPortID] = flowIDList
321 f.flowsUsedByGemPortKey.Unlock()
322
323 // update the flowids for a gem to the KVstore
324 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400325}
326
Girish Gowdra9602eb42020-09-09 15:50:39 -0700327func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000328 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200329 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000330 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530331 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700332 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530333
Neha Sharma96b7bf22020-06-15 10:37:32 +0000334 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530335 "device-id": f.deviceHandler.device.Id,
336 "intf-id": intfID,
337 "onu-id": onuID,
338 "uni-id": uniID,
339 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700340 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530341 "action": actionInfo,
342 "usmeter-iD": UsMeterID,
343 "dsmeter-iD": DsMeterID,
344 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400345 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
346 // is because the flow is an NNI flow and there would be no onu resources associated with it
347 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400348 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200349 cause := "no-onu-id-for-flow"
350 fields := log.Fields{
351 "onu": onuID,
352 "port-no": portNo,
353 "classifer": classifierInfo,
354 "action": actionInfo,
355 "device-id": f.deviceHandler.device.Id}
356 logger.Errorw(ctx, cause, fields)
357 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530358 }
359
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700360 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000361 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530362 "uni": uni,
363 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530364
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700365 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
366 "device-id": f.deviceHandler.device.Id,
367 "intf-id": intfID,
368 "onu-id": onuID,
369 "uni-id": uniID,
370 "port-no": portNo,
371 "classifier": classifierInfo,
372 "action": actionInfo,
373 "usmeter-id": UsMeterID,
374 "dsmeter-id": DsMeterID,
375 "tp-id": TpID})
376 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
377 if allocID == 0 || gemPorts == nil || TpInst == nil {
378 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
379 return olterrors.NewErrNotFound(
380 "alloc-id-gem-ports-tp-unavailable",
381 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400382 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700383 args := make(map[string]uint32)
384 args[IntfID] = intfID
385 args[OnuID] = onuID
386 args[UniID] = uniID
387 args[PortNo] = portNo
388 args[AllocID] = allocID
389
390 /* Flows can be added specific to gemport if p-bits are received.
391 * If no pbit mentioned then adding flows for all gemports
392 */
393 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
394
Andrea Campanellabfe08432020-09-11 17:07:03 +0200395 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530396}
397
salmansiddiqui7ac62132019-08-22 03:58:50 +0000398// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530399func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400
Neha Sharma96b7bf22020-06-15 10:37:32 +0000401 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530402 log.Fields{"dir": sq.direction,
403 "intf-id": sq.intfID,
404 "onu-id": sq.onuID,
405 "uni-id": sq.uniID,
406 "tp-id": sq.tpID,
407 "meter-id": sq.meterID,
408 "tp-inst": sq.tpInst,
409 "flowmetadata": sq.flowMetadata,
410 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400411
Gamze Abakafee36392019-10-03 11:17:24 +0000412 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000413 if err != nil {
414 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400415 }
416
417 /* Lets make a simple assumption that if the meter-id is present on the KV store,
418 * then the scheduler and queues configuration is applied on the OLT device
419 * in the given direction.
420 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000421
Manikkaraj kb1d51442019-07-23 10:41:02 -0400422 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530423 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530425 return olterrors.NewErrNotFound("meter",
426 log.Fields{"intf-id": sq.intfID,
427 "onu-id": sq.onuID,
428 "uni-id": sq.uniID,
429 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400430 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000431
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000433 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400435 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530437 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800438 "unsupported": "meter-id",
439 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530440 "meter-id-in-flow": sq.meterID,
441 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000443
Neha Sharma96b7bf22020-06-15 10:37:32 +0000444 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530445 log.Fields{
446 "meter-id": sq.meterID,
447 "direction": Direction,
448 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000449
Gamze Abakafee36392019-10-03 11:17:24 +0000450 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000451 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000452 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400454 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000455
456 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530457 return olterrors.NewErrNotFound("scheduler-config",
458 log.Fields{
459 "intf-id": sq.intfID,
460 "direction": sq.direction,
461 "tp-inst": sq.tpInst,
462 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000463 }
464
Manikkaraj kb1d51442019-07-23 10:41:02 -0400465 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000466 if sq.flowMetadata != nil {
467 for _, meter := range sq.flowMetadata.Meters {
468 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530471 log.Fields{"meterConfig": meterConfig,
472 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400473 break
474 }
475 }
476 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000477 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
479 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530480 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800481 "reason": "Could-not-get-meterbands-from-flowMetadata",
482 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530483 "meter-id": sq.meterID,
484 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000486 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530487 log.Fields{"Bands": meterConfig.Bands,
488 "meter-id": sq.meterID,
489 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530490 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800491 "reason": "Invalid-number-of-bands-in-meter",
492 "meterband-count": len(meterConfig.Bands),
493 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530494 "meter-id": sq.meterID,
495 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400496 }
497 cir := meterConfig.Bands[0].Rate
498 cbs := meterConfig.Bands[0].BurstSize
499 eir := meterConfig.Bands[1].Rate
500 ebs := meterConfig.Bands[1].BurstSize
501 pir := cir + eir
502 pbs := cbs + ebs
503 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
504
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700505 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000506 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400507
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700508 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530509 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400513 }
514
salmansiddiqui7ac62132019-08-22 03:58:50 +0000515 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400516 * store the meter id on the KV store, for further reference.
517 */
npujarec5762e2020-01-01 14:08:48 +0530518 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 +0530519 return olterrors.NewErrAdapter("failed-updating-meter-id",
520 log.Fields{"onu-id": sq.onuID,
521 "meter-id": sq.meterID,
522 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400523 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000524 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530525 log.Fields{"direction": Direction,
526 "Meter": meterConfig,
527 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400528 return nil
529}
530
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700531func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000532 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533
534 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530535 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
536 log.Fields{"intf-id": sq.intfID,
537 "direction": sq.direction,
538 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539 }
540
Neha Sharma96b7bf22020-06-15 10:37:32 +0000541 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530542 log.Fields{
543 "direction": sq.direction,
544 "TrafficScheds": TrafficSched,
545 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530546 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000547 IntfId: sq.intfID, OnuId: sq.onuID,
548 UniId: sq.uniID, PortNo: sq.uniPort,
549 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000550 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000552 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530553 "direction": sq.direction,
554 "traffic-queues": trafficQueues,
555 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000556
557 // On receiving the CreateTrafficQueues request, the driver should create corresponding
558 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000559 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530560 log.Fields{"direction": sq.direction,
561 "traffic-queues": trafficQueues,
562 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530563 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000564 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
565 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000566 TrafficQueues: trafficQueues,
567 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530568 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000569 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000570 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530571 "direction": sq.direction,
572 "traffic-queues": trafficQueues,
573 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000574
Esin Karamanccb714b2019-11-29 15:02:06 +0000575 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000576 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000577 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700578 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 //assumed that there is only one queue per PON for the multicast service
580 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
581 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 gemPortID: multicastQueuePerPonPort.GemportId,
586 servicePriority: multicastQueuePerPonPort.Priority,
587 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700588 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400590 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
591 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
592 return err
593 }
Shrey Baid26912972020-04-16 21:02:31 +0530594
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 }
597 }
598 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599 return nil
600}
601
salmansiddiqui7ac62132019-08-22 03:58:50 +0000602// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530603func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604
605 var Direction string
606 var SchedCfg *tp_pb.SchedulerConfig
607 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000608 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530609 log.Fields{
610 "direction": sq.direction,
611 "intf-id": sq.intfID,
612 "onu-id": sq.onuID,
613 "uni-id": sq.uniID,
614 "uni-port": sq.uniPort,
615 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000616 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000617 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400618 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000619 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400621 Direction = "downstream"
622 }
623
Girish Kumar8f73fe02019-12-09 13:19:37 +0000624 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530625 return olterrors.NewErrNotFound("scheduler-config",
626 log.Fields{
627 "int-id": sq.intfID,
628 "direction": sq.direction,
629 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000630 }
631
npujarec5762e2020-01-01 14:08:48 +0530632 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530634 return olterrors.NewErrNotFound("meter",
635 log.Fields{
636 "onu-id": sq.onuID,
637 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400638 }
639 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000640 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530641 log.Fields{
642 "direction": Direction,
643 "intf-id": sq.intfID,
644 "onu-id": sq.onuID,
645 "uni-id": sq.uniID,
646 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400647 return nil
648 }
649 cir := KVStoreMeter.Bands[0].Rate
650 cbs := KVStoreMeter.Bands[0].BurstSize
651 eir := KVStoreMeter.Bands[1].Rate
652 ebs := KVStoreMeter.Bands[1].BurstSize
653 pir := cir + eir
654 pbs := cbs + ebs
655
656 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
657
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700658 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000659 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000660
Neha Sharma96b7bf22020-06-15 10:37:32 +0000661 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000662 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530663 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
664 log.Fields{
665 "intf-id": sq.intfID,
666 "direction": sq.direction,
667 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000668 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669
npujarec5762e2020-01-01 14:08:48 +0530670 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000671 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
672 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000673 TrafficQueues: TrafficQueues,
674 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000675 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530676 log.Fields{
677 "intf-id": sq.intfID,
678 "traffic-queues": TrafficQueues,
679 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530682 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000683 IntfId: sq.intfID, OnuId: sq.onuID,
684 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000686 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530687 log.Fields{
688 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700689 "traffic-schedulers": TrafficSched,
690 "onu-id": sq.onuID,
691 "uni-id": sq.uniID,
692 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400693 }
694
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700695 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
696 log.Fields{"device-id": f.deviceHandler.device.Id,
697 "intf-id": sq.intfID,
698 "onu-id": sq.onuID,
699 "uni-id": sq.uniID,
700 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000701
702 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400703 * delete the meter id on the KV store.
704 */
npujarec5762e2020-01-01 14:08:48 +0530705 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400706 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530707 return olterrors.NewErrAdapter("unable-to-remove-meter",
708 log.Fields{
709 "onu": sq.onuID,
710 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700711 "device-id": f.deviceHandler.device.Id,
712 "intf-id": sq.intfID,
713 "onu-id": sq.onuID,
714 "uni-id": sq.uniID,
715 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400716 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000717 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530718 log.Fields{
719 "meter-id": KVStoreMeter.MeterId,
720 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700721 "device-id": f.deviceHandler.device.Id,
722 "intf-id": sq.intfID,
723 "onu-id": sq.onuID,
724 "uni-id": sq.uniID,
725 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400726 return err
727}
728
Gamze Abakafee36392019-10-03 11:17:24 +0000729// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700730func (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 +0000731 var allocIDs []uint32
732 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530733 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530734 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000735 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000736
npujarec5762e2020-01-01 14:08:48 +0530737 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
738 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000739 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530740
Neha Sharma96b7bf22020-06-15 10:37:32 +0000741 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530742 "intf-id": intfID,
743 "onu-id": onuID,
744 "uni-id": uniID,
745 "device-id": f.deviceHandler.device.Id,
746 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530747
Manikkaraj kb1d51442019-07-23 10:41:02 -0400748 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530749 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000750 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000751 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530752 log.Fields{
753 "path": tpPath,
754 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530755 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000756 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530757 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000758 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530759 log.Fields{
760 "error": err,
761 "tp-id": TpID,
762 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000763 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530764 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400765 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
766 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
767 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530768 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000769 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530770 log.Fields{
771 "uni": uni,
772 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530773 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530774 }
Gamze Abakafee36392019-10-03 11:17:24 +0000775
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700776 switch tpInst := techProfileInstance.(type) {
777 case *tp.TechProfile:
778 if UsMeterID != 0 {
779 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
780 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
781 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000782 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783 log.Fields{
784 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700785 "onu-id": onuID,
786 "uni-id": uniID,
787 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700788 "meter-id": UsMeterID,
789 "device-id": f.deviceHandler.device.Id})
790 return 0, nil, nil
791 }
792 }
793 if DsMeterID != 0 {
794 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
795 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
796 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700798 log.Fields{
799 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700800 "onu-id": onuID,
801 "uni-id": uniID,
802 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700803 "meter-id": DsMeterID,
804 "device-id": f.deviceHandler.device.Id})
805 return 0, nil, nil
806 }
807 }
808 allocID := tpInst.UsScheduler.AllocID
809 for _, gem := range tpInst.UpstreamGemPortAttributeList {
810 gemPortIDs = append(gemPortIDs, gem.GemportID)
811 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700812 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000813
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700814 if tpInstanceExists {
815 return allocID, gemPortIDs, techProfileInstance
816 }
817
818 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700819 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700820 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000821 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700822 log.Fields{
823 "alloc-ids": allocIDs,
824 "gemports": allgemPortIDs,
825 "device-id": f.deviceHandler.device.Id})
826 // Send Tconts and GEM ports to KV store
827 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530828 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700829 case *tp.EponProfile:
830 // CreateSchedulerQueues for EPON needs to be implemented here
831 // when voltha-protos for EPON is completed.
832 allocID := tpInst.AllocID
833 for _, gem := range tpInst.UpstreamQueueAttributeList {
834 gemPortIDs = append(gemPortIDs, gem.GemportID)
835 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700836 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700837
838 if tpInstanceExists {
839 return allocID, gemPortIDs, techProfileInstance
840 }
841
842 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700843 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700844 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000845 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 log.Fields{
847 "alloc-ids": allocIDs,
848 "gemports": allgemPortIDs,
849 "device-id": f.deviceHandler.device.Id})
850 // Send Tconts and GEM ports to KV store
851 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
852 return allocID, gemPortIDs, techProfileInstance
853 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000854 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 log.Fields{
856 "tpInst": tpInst})
857 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530858 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530859}
860
npujarec5762e2020-01-01 14:08:48 +0530861func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530862
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530864 log.Fields{
865 "intf-id": intfID,
866 "onu-id": onuID,
867 "uni-id": uniID,
868 "alloc-id": allocID,
869 "gemport-ids": gemPortIDs,
870 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530871 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530872 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000873 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 +0530874 }
npujarec5762e2020-01-01 14:08:48 +0530875 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000876 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 +0530877 }
npujarec5762e2020-01-01 14:08:48 +0530878 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000879 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 +0000880 } else {
881 //add to gem to uni cache
882 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530883 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000884 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 -0400885 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530886 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400887 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530888}
889
Esin Karamandf392e12020-12-16 13:33:09 +0000890//addGemPortUniAssociationsToCache
891func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
892 for _, gemPortID := range gemPortIDs {
893 key := gemPortKey{
894 intfID: intfID,
895 gemPort: gemPortID,
896 }
897 f.toGemToUniMap(ctx, key, onuID, uniID)
898 }
899 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
900 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
901}
902
Neha Sharma96b7bf22020-06-15 10:37:32 +0000903func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000904 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530905 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000906 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700907 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400908 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000909 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530910 log.Fields{
911 "intf-id": intfID,
912 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530913 }
914 }
915 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400916 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530917 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530918 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800919 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530920 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
921 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530922 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000923 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530924 log.Fields{
925 "numofTech": tpCount,
926 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
927 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530928 return nil
929}
930
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700931func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530932 portNo uint32, uplinkClassifier map[string]interface{},
933 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700934 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700935 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000936 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530937 log.Fields{
938 "uplinkClassifier": uplinkClassifier,
939 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700940 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
941 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530942 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530943}
944
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700945func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530946 portNo uint32, downlinkClassifier map[string]interface{},
947 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700948 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700949 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000950 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530951 log.Fields{
952 "downlinkClassifier": downlinkClassifier,
953 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400954 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
955 if vlan, exists := downlinkClassifier[VlanVid]; exists {
956 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700957 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
959 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530960 log.Fields{
961 "flow": logicalFlow,
962 "device-id": f.deviceHandler.device.Id,
963 "onu-id": onuID,
964 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400966 }
967 }
968 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530969 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400970
Manikkaraj k884c1242019-04-11 16:26:42 +0530971 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700972 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400973 // vlan_vid is a uint32. must be type asserted as such or conversion fails
974 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530975 if ok {
976 downlinkAction[VlanVid] = dlClVid & 0xfff
977 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530978 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530979 "reason": "failed-to-convert-vlanid-classifier",
980 "vlan-id": VlanVid,
981 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530982 }
983
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700984 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
985 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530986}
987
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700988func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Manikkaraj k884c1242019-04-11 16:26:42 +0530989 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700990 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
991
992 var inverseDirection string
993 if direction == Upstream {
994 inverseDirection = Downstream
995 } else {
996 inverseDirection = Upstream
997 }
998
Neha Sharma96b7bf22020-06-15 10:37:32 +0000999 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301000 log.Fields{
1001 "intf-id": intfID,
1002 "onu-id": onuID,
1003 "uni-id": uniID,
1004 "device-id": f.deviceHandler.device.Id,
1005 "classifier": classifier,
1006 "action": action,
1007 "direction": direction,
1008 "alloc-id": allocID,
1009 "gemport-id": gemPortID,
1010 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001011
1012 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001013 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301014 log.Fields{
1015 "device-id": f.deviceHandler.device.Id,
1016 "intf-id": intfID,
1017 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001018 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301019 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001020 classifierProto, err := makeOpenOltClassifierField(classifier)
1021 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301022 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301023 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301025 log.Fields{
1026 "classifier": *classifierProto,
1027 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001028 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001029 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301030 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301031 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001032 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301033 log.Fields{
1034 "action": *actionProto,
1035 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001036 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301037 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301038 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001039 log.Fields{
1040 "classifier": classifier,
1041 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301042 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001043 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301044 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001045
1046 // Get symmetric flowID if it exists
1047 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1048 // symmetric flow earlier
1049 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1050 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1051 f.subscriberDataPathFlowIDMapLock.RLock()
1052 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1053 f.subscriberDataPathFlowIDMapLock.RUnlock()
1054
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001055 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001056 OnuId: int32(onuID),
1057 UniId: int32(uniID),
1058 FlowId: logicalFlow.Id,
1059 FlowType: direction,
1060 AllocId: int32(allocID),
1061 NetworkIntfId: int32(networkIntfID),
1062 GemportId: int32(gemPortID),
1063 Classifier: classifierProto,
1064 Action: actionProto,
1065 Priority: int32(logicalFlow.Priority),
1066 Cookie: logicalFlow.Cookie,
1067 PortNo: portNo,
1068 TechProfileId: tpID,
1069 ReplicateFlow: len(pbitToGem) > 0,
1070 PbitToGemport: pbitToGem,
1071 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001072 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001073 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001074 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{"direction": direction,
1078 "device-id": f.deviceHandler.device.Id,
1079 "flow": flow,
1080 "intf-id": intfID,
1081 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001082 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1083 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1084 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "flow": flow,
1087 "device-id": f.deviceHandler.device.Id,
1088 "intf-id": intfID,
1089 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001091
1092 // Update the current flowID to the map
1093 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1094 f.subscriberDataPathFlowIDMapLock.Lock()
1095 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1096 f.subscriberDataPathFlowIDMapLock.Unlock()
1097
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301099}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001100
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001101func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1102 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001103 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301104
Neha Sharma96b7bf22020-06-15 10:37:32 +00001105 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301106 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301107 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001108 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301109 "action": action,
1110 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301112 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301113
1114 // Clear the action map
1115 for k := range action {
1116 delete(action, k)
1117 }
1118
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001119 action[TrapToHost] = true
1120 classifier[UDPSrc] = uint32(68)
1121 classifier[UDPDst] = uint32(67)
1122 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301123
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001124 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301126 log.Fields{
1127 "device-id": f.deviceHandler.device.Id,
1128 "intf-id": intfID,
1129 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001130 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301131 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132
Neha Sharma96b7bf22020-06-15 10:37:32 +00001133 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301134 log.Fields{
1135 "ul_classifier": classifier,
1136 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001137 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301138 "intf-id": intfID,
1139 "onu-id": onuID,
1140 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301141
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 classifierProto, err := makeOpenOltClassifierField(classifier)
1143 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301144 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301145 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001147 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301149 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301150 }
1151
David K. Bainbridge794735f2020-02-11 21:01:37 -08001152 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001153 OnuId: int32(onuID),
1154 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001155 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001156 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001157 AllocId: int32(allocID),
1158 NetworkIntfId: int32(networkIntfID),
1159 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301160 Classifier: classifierProto,
1161 Action: actionProto,
1162 Priority: int32(logicalFlow.Priority),
1163 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001164 PortNo: portNo,
1165 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001166 ReplicateFlow: len(pbitToGem) > 0,
1167 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001168 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001169 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001170 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001172 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301173 log.Fields{
1174 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "intf-id": intfID,
1177 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001178 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1179 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 +05301180 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1181 log.Fields{
1182 "flow": dhcpFlow,
1183 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301184 }
1185
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301187}
1188
Esin Karamanae41e2b2019-12-17 18:13:13 +00001189//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301190func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001191 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1192 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001193}
1194
1195//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301196func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32, classifier map[string]interface{},
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001197 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Esin Karamanae41e2b2019-12-17 18:13:13 +00001198
Neha Sharma96b7bf22020-06-15 10:37:32 +00001199 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001200 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301201 return olterrors.NewErrNotFound("nni-interface-id",
1202 log.Fields{
1203 "classifier": classifier,
1204 "action": action,
1205 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001207 }
1208
1209 // Clear the action map
1210 for k := range action {
1211 delete(action, k)
1212 }
1213
1214 action[TrapToHost] = true
1215 classifier[PacketTagType] = SingleTag
1216 delete(classifier, VlanVid)
1217
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001218 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001219 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221 }
1222
Neha Sharma96b7bf22020-06-15 10:37:32 +00001223 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301224 log.Fields{
1225 "ul_classifier": classifier,
1226 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001227 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301228 "device-id": f.deviceHandler.device.Id,
1229 "intf-id": intfID,
1230 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001231
David K. Bainbridge794735f2020-02-11 21:01:37 -08001232 classifierProto, err := makeOpenOltClassifierField(classifier)
1233 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301234 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001235 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001236 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301237 log.Fields{
1238 "classifier": *classifierProto,
1239 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001240 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301242 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001243 }
1244
David K. Bainbridge794735f2020-02-11 21:01:37 -08001245 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001246 OnuId: int32(onuID),
1247 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001248 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001249 FlowType: Upstream,
1250 AllocId: int32(allocID),
1251 NetworkIntfId: int32(networkIntfID),
1252 GemportId: int32(gemPortID),
1253 Classifier: classifierProto,
1254 Action: actionProto,
1255 Priority: int32(logicalFlow.Priority),
1256 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001257 PortNo: portNo,
1258 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001259 ReplicateFlow: len(pbitToGem) > 0,
1260 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001261 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001264 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 -08001265 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001267 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1268 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 +05301269 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 +00001270 }
1271
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273}
1274
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001275// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001276func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1277 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001278 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001279 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301280 log.Fields{
1281 "intf-id": intfID,
1282 "onu-id": onuID,
1283 "port-no": portNo,
1284 "alloc-id": allocID,
1285 "gemport-id": gemPortID,
1286 "vlan-id": vlanID,
1287 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301288
1289 uplinkClassifier := make(map[string]interface{})
1290 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301291
manikkaraj kbf256be2019-03-25 00:13:48 +05301292 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001293 uplinkClassifier[EthType] = uint32(EapEthType)
1294 uplinkClassifier[PacketTagType] = SingleTag
1295 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001296 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301297 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001298 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001299 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001300 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301301 "device-id": f.deviceHandler.device.Id,
1302 "onu-id": onuID,
1303 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301305 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301306 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001307 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301308 log.Fields{
1309 "ul_classifier": uplinkClassifier,
1310 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001311 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301312 "device-id": f.deviceHandler.device.Id,
1313 "intf-id": intfID,
1314 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301315
David K. Bainbridge794735f2020-02-11 21:01:37 -08001316 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1317 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301318 return olterrors.NewErrInvalidValue(log.Fields{
1319 "classifier": uplinkClassifier,
1320 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301321 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001322 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301323 log.Fields{
1324 "classifier": *classifierProto,
1325 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001326 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301328 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301329 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001330 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301331 log.Fields{
1332 "action": *actionProto,
1333 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001334 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301335 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301336 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301338 "action": action,
1339 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301341 }
1342
David K. Bainbridge794735f2020-02-11 21:01:37 -08001343 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001344 OnuId: int32(onuID),
1345 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001346 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001347 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 AllocId: int32(allocID),
1349 NetworkIntfId: int32(networkIntfID),
1350 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 Classifier: classifierProto,
1352 Action: actionProto,
1353 Priority: int32(logicalFlow.Priority),
1354 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001355 PortNo: portNo,
1356 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001357 ReplicateFlow: len(pbitToGem) > 0,
1358 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001359 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001361 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001363 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301364 log.Fields{
1365 "device-id": f.deviceHandler.device.Id,
1366 "onu-id": onuID,
1367 "intf-id": intfID,
1368 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001369 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1370 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 +05301371 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1372 log.Fields{
1373 "flow": upstreamFlow,
1374 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001376 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301377}
1378
David K. Bainbridge794735f2020-02-11 21:01:37 -08001379func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001380 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001381
1382 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1383 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1384 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001385 if vlanID != ReservedVlan {
1386 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001387 classifier.OVid = vid
1388 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301389 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001390 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1391 vid := uint32(metadata)
1392 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001393 classifier.IVid = vid
1394 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301395 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301396 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001397 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301398 classifier.OPbits = vlanPcp
1399 } else {
1400 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301401 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001402 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1403 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1404 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1405 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001406 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001407 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1408 classifier.PktTagType = pktTagType
1409
1410 switch pktTagType {
1411 case SingleTag:
1412 case DoubleTag:
1413 case Untagged:
1414 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001415 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301416 }
1417 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001418 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301419}
1420
Gamze Abaka724d0852020-03-18 12:10:24 +00001421func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001422 var actionCmd openoltpb2.ActionCmd
1423 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301424 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001425 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301426 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001427 if _, ok := actionInfo[VlanPcp]; ok {
1428 action.Cmd.RemarkInnerPbits = true
1429 action.IPbits = actionInfo[VlanPcp].(uint32)
1430 if _, ok := actionInfo[VlanVid]; ok {
1431 action.Cmd.TranslateInnerTag = true
1432 action.IVid = actionInfo[VlanVid].(uint32)
1433 }
1434 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001435 } else if _, ok := actionInfo[PushVlan]; ok {
1436 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301437 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001438 if _, ok := actionInfo[VlanPcp]; ok {
1439 action.OPbits = actionInfo[VlanPcp].(uint32)
1440 action.Cmd.RemarkOuterPbits = true
1441 if _, ok := classifierInfo[VlanVid]; ok {
1442 action.IVid = classifierInfo[VlanVid].(uint32)
1443 action.Cmd.TranslateInnerTag = true
1444 }
1445 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001446 } else if _, ok := actionInfo[TrapToHost]; ok {
1447 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001449 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001451 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301452}
1453
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001454// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001455func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1456 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301457}
1458
Gamze Abakafee36392019-10-03 11:17:24 +00001459// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001460func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301461 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001462 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1463
Gamze Abakafee36392019-10-03 11:17:24 +00001464 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301465 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001466 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301467 // return err
1468 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001469 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001470 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001471 }
1472 return nil
1473}
1474
1475// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301476func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001477 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001478 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001479 }
npujarec5762e2020-01-01 14:08:48 +05301480 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301481 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1482 log.Fields{
1483 "tp-id": tpID,
1484 "uni-port-name": uniPortName,
1485 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001486 }
1487 return nil
1488}
1489
David K. Bainbridge794735f2020-02-11 21:01:37 -08001490func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001491
1492 var intfID uint32
1493 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1494 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1495 */
1496 if deviceFlow.AccessIntfId != -1 {
1497 intfID = uint32(deviceFlow.AccessIntfId)
1498 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001499 // We need to log the valid interface ID.
1500 // 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 +00001501 intfID = uint32(deviceFlow.NetworkIntfId)
1502 }
1503
Neha Sharma96b7bf22020-06-15 10:37:32 +00001504 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301505 "flow": *deviceFlow,
1506 "device-id": f.deviceHandler.device.Id,
1507 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001508 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001509
1510 st, _ := status.FromError(err)
1511 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001513 "err": err,
1514 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301515 "device-id": f.deviceHandler.device.Id,
1516 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001517 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301518 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001519
1520 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001521 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301522 log.Fields{"err": err,
1523 "device-flow": deviceFlow,
1524 "device-id": f.deviceHandler.device.Id,
1525 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001526 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001527 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001528 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301529 log.Fields{
1530 "flow": *deviceFlow,
1531 "device-id": f.deviceHandler.device.Id,
1532 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001533
1534 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1535 if deviceFlow.AccessIntfId != -1 {
1536 // No need to register the flow if it is a trap on nni flow.
1537 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1538 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1539 return err
1540 }
1541 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001542 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001543}
1544
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1546 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301547 log.Fields{
1548 "flow": *deviceFlow,
1549 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001550 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001551 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001552 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001553 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301554 log.Fields{
1555 "err": err,
1556 "deviceFlow": deviceFlow,
1557 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001558 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001559 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001560 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001561 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001562
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001563 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001564 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001565 "of-flow-id": ofFlowID,
1566 "flow": *deviceFlow,
1567 "device-id": f.deviceHandler.device.Id,
1568 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001569 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301570}
1571
David K. Bainbridge794735f2020-02-11 21:01:37 -08001572func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001573
1574 classifierInfo := make(map[string]interface{})
1575 actionInfo := make(map[string]interface{})
1576
1577 classifierInfo[EthType] = uint32(LldpEthType)
1578 classifierInfo[PacketTagType] = Untagged
1579 actionInfo[TrapToHost] = true
1580
1581 // LLDP flow is installed to trap LLDP packets on the NNI port.
1582 // We manage flow_id resource pool on per PON port basis.
1583 // Since this situation is tricky, as a hack, we pass the NNI port
1584 // index (network_intf_id) as PON port Index for the flow_id resource
1585 // pool. Also, there is no ONU Id available for trapping LLDP packets
1586 // on NNI port, use onu_id as -1 (invalid)
1587 // ****************** CAVEAT *******************
1588 // This logic works if the NNI Port Id falls within the same valid
1589 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1590 // we need to have a re-look at this.
1591 // *********************************************
1592
1593 var onuID = -1
1594 var uniID = -1
1595 var gemPortID = -1
1596
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001598 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301599 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001601 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001602 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001603 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001604 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001605
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1607 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301608 return olterrors.NewErrInvalidValue(
1609 log.Fields{
1610 "classifier": classifierInfo,
1611 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001612 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001613 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301614 log.Fields{
1615 "classifier": *classifierProto,
1616 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001617 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001618 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301619 return olterrors.NewErrInvalidValue(
1620 log.Fields{
1621 "action": actionInfo,
1622 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001623 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301625 log.Fields{
1626 "action": *actionProto,
1627 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001628
1629 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1630 OnuId: int32(onuID), // OnuId not required
1631 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001632 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001633 FlowType: Downstream,
1634 NetworkIntfId: int32(networkInterfaceID),
1635 GemportId: int32(gemPortID),
1636 Classifier: classifierProto,
1637 Action: actionProto,
1638 Priority: int32(flow.Priority),
1639 Cookie: flow.Cookie,
1640 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001641 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001642 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301643 log.Fields{
1644 "flow": downstreamflow,
1645 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001646 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{
1649 "device-id": f.deviceHandler.device.Id,
1650 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001651 "flow-id": flow.Id})
1652 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1653 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1654 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301655 log.Fields{
1656 "flow": downstreamflow,
1657 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 }
1659 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301660}
1661
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001662func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1663 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001664}
1665
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001666//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001668 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1669 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1670 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
1673 "intf-id": intfID,
1674 "onu-id": onuID,
1675 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001676 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001677 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301678 return nil, olterrors.NewErrNotFound("onu-child-device",
1679 log.Fields{
1680 "onu-id": onuID,
1681 "intf-id": intfID,
1682 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001683 }
1684 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1685 //better to ad the device to cache here.
1686 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1687 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001688 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301689 log.Fields{
1690 "intf-id": intfID,
1691 "onu-id": onuID,
1692 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001693 }
1694
1695 return onuDev.(*OnuDevice), nil
1696}
1697
1698//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001699func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1700 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301701 log.Fields{
1702 "pon-port": intfID,
1703 "onu-id": onuID,
1704 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001705 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001706 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001707 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301708 return nil, olterrors.NewErrNotFound("onu",
1709 log.Fields{
1710 "interface-id": parentPortNo,
1711 "onu-id": onuID,
1712 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001713 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301714 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301716 log.Fields{
1717 "device-id": f.deviceHandler.device.Id,
1718 "child_device_id": onuDevice.Id,
1719 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301720 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301721}
1722
Neha Sharma96b7bf22020-06-15 10:37:32 +00001723func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1724 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301725 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301727 log.Fields{
1728 "intf-id": intfID,
1729 "onu-id": onuID,
1730 "uni-id": uniID,
1731 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301733 }
1734
1735 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001736 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301737 log.Fields{
1738 "msg": *delGemPortMsg,
1739 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001740 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301741 delGemPortMsg,
1742 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001743 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001744 onuDev.deviceType,
1745 onuDev.deviceID,
1746 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301747 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1748 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001749 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301750 "to-adapter": onuDev.deviceType,
1751 "onu-id": onuDev.deviceID,
1752 "proxyDeviceID": onuDev.proxyDeviceID,
1753 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301754 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301756 log.Fields{
1757 "msg": delGemPortMsg,
1758 "from-adapter": f.deviceHandler.device.Type,
1759 "to-adapter": onuDev.deviceType,
1760 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301761 return nil
1762}
1763
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1765 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301766 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301768 log.Fields{
1769 "intf-id": intfID,
1770 "onu-id": onuID,
1771 "uni-id": uniID,
1772 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001773 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301774 }
1775
1776 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301778 log.Fields{
1779 "msg": *delTcontMsg,
1780 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001781 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301782 delTcontMsg,
1783 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001784 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001785 onuDev.deviceType,
1786 onuDev.deviceID,
1787 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301788 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1789 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001790 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301791 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1792 "proxyDeviceID": onuDev.proxyDeviceID,
1793 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301794 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001795 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301796 log.Fields{
1797 "msg": delTcontMsg,
1798 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301799 return nil
1800}
1801
Girish Gowdrac3037402020-01-22 20:29:53 +05301802// Once the gemport is released for a given onu, it also has to be cleared from local cache
1803// which was used for deriving the gemport->logicalPortNo during packet-in.
1804// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1805// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001807
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001808 f.onuGemInfoLock.Lock()
1809 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001810
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301812 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001813 "gem-port-id": gemPortID,
1814 "intf-id": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001817 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001818
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001819 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001820deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001821 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301822 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001823 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301824 // If the gemport is found, delete it from local cache.
1825 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001826 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1827 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001828 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301829 log.Fields{
1830 "intf-id": intfID,
1831 "onu-id": onuID,
1832 "deletedgemport-id": gemPortID,
1833 "gemports": onu.GemPorts,
1834 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001835 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301836 }
1837 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001838 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301839 }
1840 }
1841}
1842
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301843//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001844// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301845func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001846 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001847
Neha Sharma96b7bf22020-06-15 10:37:32 +00001848 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001849 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301850 return olterrors.NewErrNotFound("tp-id",
1851 log.Fields{
1852 "flow": flow,
1853 "intf": Intf,
1854 "onu-id": onuID,
1855 "uni-id": uniID,
1856 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001857 }
Gamze Abakafee36392019-10-03 11:17:24 +00001858
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001859 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1860 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1861 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1862 log.Fields{
1863 "tpPath": tpPath,
1864 "device-id": f.deviceHandler.device.Id})
1865 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1866 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1867 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1868 log.Fields{
1869 "tp-id": tpID,
1870 "path": tpPath}, err)
1871 }
1872
1873 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1874
1875 if used {
1876 f.flowsUsedByGemPortKey.Lock()
1877 defer f.flowsUsedByGemPortKey.Unlock()
1878
1879 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1880 for i, flowIDinMap := range flowIDs {
1881 if flowIDinMap == flowID {
1882 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1883 // everytime flowsUsedByGemPort cache is updated the same should be updated
1884 // in kv store by calling UpdateFlowIDsForGem
1885 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1886 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1887 return err
1888 }
1889 break
1890 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001891 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001892 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1893 log.Fields{
1894 "gemport-id": gemPortID,
1895 "usedByFlows": flowIDs,
1896 "device-id": f.deviceHandler.device.Id})
1897 return nil
1898 }
1899 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1900 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1901 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1902 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1903 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Esin Karamandf392e12020-12-16 13:33:09 +00001904 // also clear gem to uni cache
1905 f.removeFromGemToUniMap(gemPortKey{
1906 intfID: Intf,
1907 gemPort: uint32(gemPortID),
1908 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001909 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001910
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001911 f.onuIdsLock.Lock() // TODO: What is this lock?
1912
1913 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1914 // by calling DeleteFlowIDsForGem
1915 f.flowsUsedByGemPortKey.Lock()
1916 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1917 f.flowsUsedByGemPortKey.Unlock()
1918 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1919 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1920
1921 f.onuIdsLock.Unlock()
1922
1923 // Delete the gem port on the ONU.
1924 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1925 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1926 log.Fields{
1927 "err": err,
1928 "intf": Intf,
1929 "onu-id": onuID,
1930 "uni-id": uniID,
1931 "device-id": f.deviceHandler.device.Id,
1932 "gemport-id": gemPortID})
1933 }
1934 switch techprofileInst := techprofileInst.(type) {
1935 case *tp.TechProfile:
1936 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1937 if !ok {
1938 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1939 logger.Warn(ctx, err)
1940 }
1941 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1942 logger.Warn(ctx, err)
1943 }
1944 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 {
1945 logger.Warn(ctx, err)
1946 }
1947 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 {
1948 logger.Warn(ctx, err)
1949 }
1950 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1951 // Delete the TCONT on the ONU.
1952 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1953 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1954 log.Fields{
1955 "intf": Intf,
1956 "onu-id": onuID,
1957 "uni-id": uniID,
1958 "device-id": f.deviceHandler.device.Id,
1959 "alloc-id": techprofileInst.UsScheduler.AllocID})
1960 }
1961 }
1962 case *tp.EponProfile:
1963 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1964 logger.Warn(ctx, err)
1965 }
1966 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1967 logger.Warn(ctx, err)
1968 }
1969 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1970 // Delete the TCONT on the ONU.
1971 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1972 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301973 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001974 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301975 "onu-id": onuID,
1976 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 "device-id": f.deviceHandler.device.Id,
1978 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001979 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001980 default:
1981 logger.Errorw(ctx, "error-unknown-tech",
1982 log.Fields{
1983 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001984 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001985
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301986 return nil
1987}
1988
David K. Bainbridge794735f2020-02-11 21:01:37 -08001989// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001990func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001991 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001992 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301993 log.Fields{
1994 "flowDirection": flowDirection,
1995 "flow": *flow,
1996 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001997
1998 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001999 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002000 }
2001
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302002 classifierInfo := make(map[string]interface{})
2003
Neha Sharma96b7bf22020-06-15 10:37:32 +00002004 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302005 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002007 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302008 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302009
David K. Bainbridge794735f2020-02-11 21:01:37 -08002010 onuID := int32(onu)
2011 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302012
2013 for _, field := range flows.GetOfbFields(flow) {
2014 if field.Type == flows.IP_PROTO {
2015 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002016 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302017 }
2018 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002019 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302020 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002021 "flow-id": flow.Id,
2022 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302023 "onu-id": onuID,
2024 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302025
2026 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2027 onuID = -1
2028 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002029 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2030 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002031 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002032 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002033 log.Fields{
2034 "port-number": inPort,
2035 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002037 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302038 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2040 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})
2041 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2042 }
2043 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2044 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2045 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2046 return err
2047 }
2048 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2049 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2050 return err
2051 }
2052 if !flowInfo.Flow.ReplicateFlow {
2053 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
2054 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2055 "flow-id": flow.Id,
2056 "stored-flow": flowInfo.Flow,
2057 "device-id": f.deviceHandler.device.Id,
2058 "stored-flow-id": flowInfo.Flow.FlowId,
2059 "onu-id": onuID,
2060 "intf": Intf,
2061 })
2062 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302063 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002064 } else {
2065 gems := make([]uint32, 0)
2066 for _, gem := range flowInfo.Flow.PbitToGemport {
2067 gems = appendUnique32bit(gems, gem)
2068 }
2069 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2070 for _, gem := range gems {
2071 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
2072 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002073 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002074 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002075 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002077 "onu-id": onuID,
2078 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002079 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002080 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002081 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302082 }
2083 }
2084 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002085
2086 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2087 if isDatapathFlow(flow) {
2088 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2089 var inverseDirection string
2090 if flowDirection == Upstream {
2091 inverseDirection = Downstream
2092 } else {
2093 inverseDirection = Upstream
2094 }
2095
2096 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002097 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002098 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002099 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100 }
2101 }
2102 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002103}
2104
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002105//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002106func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002107
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302109 var direction string
2110 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002111
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302112 for _, action := range flows.GetActions(flow) {
2113 if action.Type == flows.OUTPUT {
2114 if out := action.GetOutput(); out != nil {
2115 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302117 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002118 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002119 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002120 }
2121 }
2122 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002123
2124 if flows.HasGroup(flow) {
2125 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002126 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002127 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302128 direction = Upstream
2129 } else {
2130 direction = Downstream
2131 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302132
Girish Gowdracefae192020-03-19 18:14:10 -07002133 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002134 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002135
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002136 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002137}
2138
Esin Karamanae41e2b2019-12-17 18:13:13 +00002139//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2140func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2141 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2142 if ethType, ok := classifierInfo[EthType]; ok {
2143 if ethType.(uint32) == IPv4EthType {
2144 if ipProto, ok := classifierInfo[IPProto]; ok {
2145 if ipProto.(uint32) == IgmpProto {
2146 return true
2147 }
2148 }
2149 }
2150 }
2151 }
2152 return false
2153}
2154
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002155// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2156func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2157 // Step1 : Fill flowControlBlock
2158 // Step2 : Push the flowControlBlock to ONU channel
2159 // Step3 : Wait on response channel for response
2160 // Step4 : Return error value
2161 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2162 errChan := make(chan error)
2163 flowCb := flowControlBlock{
2164 ctx: ctx,
2165 addFlow: addFlow,
2166 flow: flow,
2167 flowMetadata: flowMetadata,
2168 errChan: &errChan,
2169 }
2170 inPort, outPort := getPorts(flow)
2171 var onuID uint32
2172 if inPort != InvalidPort && outPort != InvalidPort {
2173 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2174 }
2175 // inPort or outPort is InvalidPort for trap-from-nni flows.
2176 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2177 // Send the flowCb on the ONU flow channel
2178 f.incomingFlows[onuID] <- flowCb
2179 // Wait on the channel for flow handlers return value
2180 err := <-errChan
2181 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2182 return err
2183}
2184
2185// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2186// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2187func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2188 for {
2189 // block on the channel to receive an incoming flow
2190 // process the flow completely before proceeding to handle the next flow
2191 flowCb := <-subscriberFlowChannel
2192 if flowCb.addFlow {
2193 logger.Debugw(flowCb.ctx, "adding-flow",
2194 log.Fields{"device-id": f.deviceHandler.device.Id,
2195 "flowToAdd": flowCb.flow})
2196 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2197 // Pass the return value over the return channel
2198 *flowCb.errChan <- err
2199 } else {
2200 logger.Debugw(flowCb.ctx, "removing-flow",
2201 log.Fields{"device-id": f.deviceHandler.device.Id,
2202 "flowToRemove": flowCb.flow})
2203 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2204 // Pass the return value over the return channel
2205 *flowCb.errChan <- err
2206 }
2207 }
2208}
2209
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002210// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302211// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002212func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002213 classifierInfo := make(map[string]interface{})
2214 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002215 var UsMeterID uint32
2216 var DsMeterID uint32
2217
Neha Sharma96b7bf22020-06-15 10:37:32 +00002218 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302219 log.Fields{
2220 "flow": flow,
2221 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002223
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002225 if err != nil {
2226 // Error logging is already done in the called function
2227 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002228 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302229 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002230
Esin Karamanccb714b2019-11-29 15:02:06 +00002231 if flows.HasGroup(flow) {
2232 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002233 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002234 }
2235
manikkaraj k17652a72019-05-06 09:06:36 -04002236 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002237 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002238 if err != nil {
2239 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002240 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002241 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002242
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302244 log.Fields{
2245 "classifierinfo_inport": classifierInfo[InPort],
2246 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002247 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002248
Humera Kouser94d7a842019-08-25 19:04:32 -04002249 if ethType, ok := classifierInfo[EthType]; ok {
2250 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002251 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002252 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002253 }
2254 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002255 if ipProto, ok := classifierInfo[IPProto]; ok {
2256 if ipProto.(uint32) == IPProtoDhcp {
2257 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302258 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002259 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002260 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002261 }
2262 }
2263 }
2264 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002265 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002266 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002267 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002268 }
A R Karthick1f85b802019-10-11 05:06:05 +00002269
npujarec5762e2020-01-01 14:08:48 +05302270 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002271
Neha Sharma96b7bf22020-06-15 10:37:32 +00002272 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002273 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302274 return olterrors.NewErrNotFound("tpid-for-flow",
2275 log.Fields{
2276 "flow": flow,
2277 "intf-id": IntfID,
2278 "onu-id": onuID,
2279 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002280 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002281 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302282 log.Fields{
2283 "tp-id": TpID,
2284 "intf-id": intfID,
2285 "onu-id": onuID,
2286 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002287 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002288 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002289 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002290 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002291 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002292 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002293
2294 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002295 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002296}
Girish Gowdra3d633032019-12-10 16:37:05 +05302297
Esin Karamanccb714b2019-11-29 15:02:06 +00002298// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002299func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002300 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302302 "classifier-info": classifierInfo,
2303 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002304
Esin Karaman65409d82020-03-18 10:58:18 +00002305 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002306 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002307 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002308 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002309
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002310 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002311
David K. Bainbridge794735f2020-02-11 21:01:37 -08002312 onuID := NoneOnuID
2313 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002314
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002315 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002317 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002318 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002319 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2320 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002321 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 }
2323 groupID := actionInfo[GroupID].(uint32)
2324 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002325 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002326 FlowType: Multicast,
2327 NetworkIntfId: int32(networkInterfaceID),
2328 GroupId: groupID,
2329 Classifier: classifierProto,
2330 Priority: int32(flow.Priority),
2331 Cookie: flow.Cookie}
2332
Kent Hagermane6ff1012020-07-14 15:07:53 -04002333 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002334 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002335 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002336 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002337 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002338 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002339 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002340 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002341 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002342 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002343 //cached group can be removed now
2344 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2345 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2346 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002347 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002348
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002349 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2350 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2351 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002352 }
2353 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002354}
2355
Esin Karaman65409d82020-03-18 10:58:18 +00002356//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2357func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2358 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002360 if err != nil {
2361 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2362 }
2363 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
Esin Karaman65409d82020-03-18 10:58:18 +00002365 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302366 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002367 if e == nil && len(nniPorts) > 0 {
2368 return nniPorts[0], nil
2369 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302370 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002371}
2372
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002375
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302377 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302379 log.Fields{
2380 "intf-id": intfID,
2381 "onu-id": onuID,
2382 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002383 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302384 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002385 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002386
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002390 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002391 tpDownloadMsg,
2392 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002393 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002394 onuDev.deviceType,
2395 onuDev.deviceID,
2396 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002397 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302398 return olterrors.NewErrCommunication("send-techprofile-download-request",
2399 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002400 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302401 "to-adapter": onuDev.deviceType,
2402 "onu-id": onuDev.deviceID,
2403 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002404 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302406 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302407}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002408
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302409//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002410func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302411
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002412 f.onuGemInfoLock.Lock()
2413 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002414 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002415 // If the ONU already exists in onuGemInfo list, nothing to do
2416 for _, onu := range onugem {
2417 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2418 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2419 log.Fields{"onuID": onuID,
2420 "serialNum": serialNum})
2421 return nil
2422 }
2423 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002424
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302425 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002426 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002427 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002428 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302429 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002430 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302431 log.Fields{
2432 "intf-id": intfID,
2433 "onu-id": onuID,
2434 "serial-num": serialNum,
2435 "onu": onu,
2436 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002437 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002438}
2439
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302440//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302441func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002442
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002443 f.onuGemInfoLock.Lock()
2444 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002445
Neha Sharma96b7bf22020-06-15 10:37:32 +00002446 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302447 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002448 "gem-port-id": gemPort,
2449 "intf-id": intfID,
2450 "onu-id": onuID,
2451 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002452 "onu-gem": f.onuGemInfo})
2453 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302454 // update the gem to the local cache as well as to kv strore
2455 for idx, onu := range onugem {
2456 if onu.OnuID == onuID {
2457 // check if gem already exists , else update the cache and kvstore
2458 for _, gem := range onu.GemPorts {
2459 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002460 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302461 log.Fields{
2462 "gem": gemPort,
2463 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302464 return
2465 }
2466 }
2467 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002468 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002469 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302470 }
2471 }
npujarec5762e2020-01-01 14:08:48 +05302472 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302473 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302475 log.Fields{
2476 "intf-id": intfID,
2477 "onu-id": onuID,
2478 "gemPort": gemPort,
2479 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002480 return
2481 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302483 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002484 "gem-port-id": gemPort,
2485 "intf-id": intfID,
2486 "onu-id": onuID,
2487 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002488 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002489}
2490
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002491//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302492func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002493 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002494 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002495 var err error
2496
2497 if packetIn.IntfType == "pon" {
2498 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002499 // get onu and uni ids associated with the given pon and gem ports
2500 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002501 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002502 return logicalPortNum, err
2503 }
Esin Karamandf392e12020-12-16 13:33:09 +00002504 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2505
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002506 if packetIn.PortNo != 0 {
2507 logicalPortNum = packetIn.PortNo
2508 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002509 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002510 }
2511 // 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 +00002512 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002513 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002514 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002515 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002516
2517 if logger.V(log.DebugLevel) {
2518 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2519 log.Fields{
2520 "logical-port-num": logicalPortNum,
2521 "intf-type": packetIn.IntfType,
2522 "packet": hex.EncodeToString(packetIn.Pkt),
2523 })
2524 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002525 return logicalPortNum, nil
2526}
2527
Esin Karamandf392e12020-12-16 13:33:09 +00002528//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2529func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2530 key := gemPortKey{
2531 intfID: intfID,
2532 gemPort: gemPortID,
2533 }
2534 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2535 if ok {
2536 if len(uniPortInfo) > 1 {
2537 //return onu ID and uni port from the cache
2538 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2539 log.Fields{
2540 "intfID": intfID,
2541 "gemPortID": gemPortID,
2542 "onuID, uniID": uniPortInfo})
2543 return uniPortInfo[0], uniPortInfo[1], nil
2544 }
2545 }
2546 //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.
2547 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2548 if err == nil {
2549 f.toGemToUniMap(ctx, key, onuID, uniID)
2550 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2551 log.Fields{
2552 "gemPortKey": key,
2553 "onuID": onuID,
2554 "uniID": uniID})
2555 return onuID, uniID, nil
2556 }
2557 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2558 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2559 errors.New("no uni port found"))
2560}
2561
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002562//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002563func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002564 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002565
2566 ctag, priority, err := getCTagFromPacket(ctx, packet)
2567 if err != nil {
2568 return 0, err
2569 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302570
Esin Karaman7fb80c22020-07-16 14:23:33 +00002571 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002572 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002573 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002574 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002575 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302576 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302578 log.Fields{
2579 "pktinkey": pktInkey,
2580 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002581
2582 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002583 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302584 //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 +00002585 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302586 if err == nil {
2587 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002588 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302589 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002590 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002591 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302592 log.Fields{
2593 "pktinkey": pktInkey,
2594 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302595 return gemPortID, nil
2596 }
2597 }
Shrey Baid26912972020-04-16 21:02:31 +05302598 return uint32(0), olterrors.NewErrNotFound("gem-port",
2599 log.Fields{
2600 "pktinkey": pktInkey,
2601 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002602
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603}
2604
David K. Bainbridge794735f2020-02-11 21:01:37 -08002605func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002606 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002607 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002608 classifier[PacketTagType] = DoubleTag
2609 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002610 /* We manage flowId resource pool on per PON port basis.
2611 Since this situation is tricky, as a hack, we pass the NNI port
2612 index (network_intf_id) as PON port Index for the flowId resource
2613 pool. Also, there is no ONU Id available for trapping DHCP packets
2614 on NNI port, use onu_id as -1 (invalid)
2615 ****************** CAVEAT *******************
2616 This logic works if the NNI Port Id falls within the same valid
2617 range of PON Port Ids. If this doesn't work for some OLT Vendor
2618 we need to have a re-look at this.
2619 *********************************************
2620 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002621 onuID := -1
2622 uniID := -1
2623 gemPortID := -1
2624 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002625 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302627 return olterrors.NewErrNotFound("nni-intreface-id",
2628 log.Fields{
2629 "classifier": classifier,
2630 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632 }
2633
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002634 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002635 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002636 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002638
David K. Bainbridge794735f2020-02-11 21:01:37 -08002639 classifierProto, err := makeOpenOltClassifierField(classifier)
2640 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002641 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002642 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002643 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002644 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002645 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002646 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002648 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002649 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2650 OnuId: int32(onuID), // OnuId not required
2651 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002652 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002653 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002654 AllocId: int32(allocID), // AllocId not used
2655 NetworkIntfId: int32(networkInterfaceID),
2656 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657 Classifier: classifierProto,
2658 Action: actionProto,
2659 Priority: int32(logicalFlow.Priority),
2660 Cookie: logicalFlow.Cookie,
2661 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002666 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2667 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2668 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002669 }
2670 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002671}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002672
Esin Karamanae41e2b2019-12-17 18:13:13 +00002673//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2674func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2675 var packetType string
2676 ovid, ivid := false, false
2677 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2678 vid := vlanID & VlanvIDMask
2679 if vid != ReservedVlan {
2680 ovid = true
2681 }
2682 }
2683 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2684 vid := uint32(metadata)
2685 if vid != ReservedVlan {
2686 ivid = true
2687 }
2688 }
2689 if ovid && ivid {
2690 packetType = DoubleTag
2691 } else if !ovid && !ivid {
2692 packetType = Untagged
2693 } else {
2694 packetType = SingleTag
2695 }
2696 return packetType
2697}
2698
2699//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002700func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002701 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002702 action := make(map[string]interface{})
2703 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2704 action[TrapToHost] = true
2705 /* We manage flowId resource pool on per PON port basis.
2706 Since this situation is tricky, as a hack, we pass the NNI port
2707 index (network_intf_id) as PON port Index for the flowId resource
2708 pool. Also, there is no ONU Id available for trapping packets
2709 on NNI port, use onu_id as -1 (invalid)
2710 ****************** CAVEAT *******************
2711 This logic works if the NNI Port Id falls within the same valid
2712 range of PON Port Ids. If this doesn't work for some OLT Vendor
2713 we need to have a re-look at this.
2714 *********************************************
2715 */
2716 onuID := -1
2717 uniID := -1
2718 gemPortID := -1
2719 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002720 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002721 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302722 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723 "classifier": classifier,
2724 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002725 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002726 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002727 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002728 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002729 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002730 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002731
David K. Bainbridge794735f2020-02-11 21:01:37 -08002732 classifierProto, err := makeOpenOltClassifierField(classifier)
2733 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002734 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002735 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002736 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002737 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002738 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002739 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002740 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002741 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002742 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2743 OnuId: int32(onuID), // OnuId not required
2744 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002745 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002746 FlowType: Downstream,
2747 AllocId: int32(allocID), // AllocId not used
2748 NetworkIntfId: int32(networkInterfaceID),
2749 GemportId: int32(gemPortID), // GemportId not used
2750 Classifier: classifierProto,
2751 Action: actionProto,
2752 Priority: int32(logicalFlow.Priority),
2753 Cookie: logicalFlow.Cookie,
2754 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002755 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002756 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002758 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002759 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2760 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2761 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002762 }
2763 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002764}
2765
salmansiddiqui7ac62132019-08-22 03:58:50 +00002766func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2767 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302768 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002769 }
2770 if Dir == tp_pb.Direction_UPSTREAM {
2771 return "upstream", nil
2772 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2773 return "downstream", nil
2774 }
2775 return "", nil
2776}
2777
Kent Hagermane6ff1012020-07-14 15:07:53 -04002778// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302779func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002780 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002781 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002782 var gemPort uint32
2783 intfID := args[IntfID]
2784 onuID := args[OnuID]
2785 uniID := args[UniID]
2786 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002787 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002788 pbitToGem := make(map[uint32]uint32)
2789
2790 if len(gemPorts) == 1 {
2791 // If there is only single gemport use that and do not populate pbitToGem map
2792 gemPort = gemPorts[0]
2793 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2794 for idx, gemID := range gemPorts {
2795 switch TpInst := TpInst.(type) {
2796 case *tp.TechProfile:
2797 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2798 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2799 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2800 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2801 // this pcp bit traffic.
2802 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2803 if pbitSet == pbit1 {
2804 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2805 pbitToGem[pcp] = gemID
2806 }
2807 }
2808 default:
2809 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2810 return
2811 }
2812 }
2813 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2814 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2815 tp_pb.Direction_UPSTREAM,
2816 pcp.(uint32))
2817 }
2818
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819 if ipProto, ok := classifierInfo[IPProto]; ok {
2820 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002821 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002822 "tp-id": tpID,
2823 "alloc-id": allocID,
2824 "intf-id": intfID,
2825 "onu-id": onuID,
2826 "uni-id": uniID,
2827 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002828 //Adding DHCP upstream flow
2829 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2830 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002831 }
2832
Girish Gowdra32625212020-04-29 11:26:35 -07002833 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002834 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302835 log.Fields{
2836 "intf-id": intfID,
2837 "onu-id": onuID,
2838 "uni-id": uniID,
2839 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002840 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2841 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002842 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002843 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002844 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002845 return
2846 }
2847 } else if ethType, ok := classifierInfo[EthType]; ok {
2848 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002849 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002850 "intf-id": intfID,
2851 "onu-id": onuID,
2852 "uni-id": uniID,
2853 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002854 var vlanID uint32
2855 if val, ok := classifierInfo[VlanVid]; ok {
2856 vlanID = (val.(uint32)) & VlanvIDMask
2857 } else {
2858 vlanID = DefaultMgmtVlan
2859 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002860 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2861 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002862 }
2863 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002864 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002865 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002866 "intf-id": intfID,
2867 "onu-id": onuID,
2868 "uni-id": uniID,
2869 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002870 //Adding HSIA upstream flow
2871 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2872 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002873 }
2874 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002875 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002876 "intf-id": intfID,
2877 "onu-id": onuID,
2878 "uni-id": uniID,
2879 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002880 //Adding HSIA downstream flow
2881 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2882 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 }
2884 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002885 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302886 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002887 "intf-id": intfID,
2888 "onu-id": onuID,
2889 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302890 "classifier": classifierInfo,
2891 "action": actionInfo,
2892 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 return
2894 }
2895 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002896 go func() {
2897 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2898 logger.Warn(ctx, err)
2899 }
2900 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901}
2902
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002903func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2904 f.flowsUsedByGemPortKey.RLock()
2905 flowIDList := f.flowsUsedByGemPort[gemPortID]
2906 f.flowsUsedByGemPortKey.RUnlock()
2907 return len(flowIDList) > 1
2908
Gamze Abakafee36392019-10-03 11:17:24 +00002909}
2910
npujarec5762e2020-01-01 14:08:48 +05302911func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2912 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002913 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2914 for _, currentGemPort := range currentGemPorts {
2915 for _, tpGemPort := range tpGemPorts {
2916 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2917 return true, currentGemPort
2918 }
2919 }
2920 }
Girish Gowdra54934262019-11-13 14:19:55 +05302921 if tpInst.InstanceCtrl.Onu == "single-instance" {
2922 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002923 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002924 logger.Warn(ctx, err)
2925 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002926 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002927 logger.Warn(ctx, err)
2928 }
Girish Gowdra54934262019-11-13 14:19:55 +05302929
2930 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2931 // still be used on other uni ports.
2932 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2933 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002934 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002935 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302936 for i := 0; i < len(tpInstances); i++ {
2937 tpI := tpInstances[i]
2938 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302939 for _, tpGemPort := range tpGemPorts {
2940 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002941 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302942 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302943 }
2944 }
2945 }
2946 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002947 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002948 return false, 0
2949}
2950
Neha Sharma96b7bf22020-06-15 10:37:32 +00002951func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002952 for _, field := range flows.GetOfbFields(flow) {
2953 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002954 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002955 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002956 } else if field.Type == flows.ETH_DST {
2957 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002958 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002959 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002961 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002962 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002963 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002964 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002965 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302966 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002968 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002971 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002973 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002974 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002977 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002978 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002980 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002981 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002983 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002984 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002986 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002987 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002989 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002990 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 return
2992 }
2993 }
2994}
2995
Neha Sharma96b7bf22020-06-15 10:37:32 +00002996func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002997 for _, action := range flows.GetActions(flow) {
2998 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002999 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003000 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003003 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 }
Scott Baker355d1742019-10-24 10:57:52 -07003005 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003008 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 if out := action.GetPush(); out != nil {
3010 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 } else {
3013 actionInfo[PushVlan] = true
3014 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303016 log.Fields{
3017 "push-tpid": actionInfo[TPID].(uint32),
3018 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 }
3020 }
Scott Baker355d1742019-10-24 10:57:52 -07003021 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003022 if out := action.GetSetField(); out != nil {
3023 if field := out.GetField(); field != nil {
3024 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003025 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003026 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3028 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003029 }
3030 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003031 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003034 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 }
3036 }
3037 return nil
3038}
3039
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003041 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003042 fieldtype := ofbField.GetType()
3043 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003044 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3045 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003047 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003049 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003050 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3051 pcp := ofbField.GetVlanPcp()
3052 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003053 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003054 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003056 }
3057 }
3058}
3059
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003061 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003063 } else {
3064 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003066 }
3067}
3068
Neha Sharma96b7bf22020-06-15 10:37:32 +00003069func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003070 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3073 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003074 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303077 log.Fields{
3078 "newinport": classifierInfo[InPort].(uint32),
3079 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303081 return olterrors.NewErrNotFound("child-in-port",
3082 log.Fields{
3083 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3084 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 }
3086 }
3087 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003088 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003089 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003090 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003091 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003092 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303094 log.Fields{
3095 "newoutport": actionInfo[Output].(uint32),
3096 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303098 return olterrors.NewErrNotFound("out-port",
3099 log.Fields{
3100 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3101 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 }
3103 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3104 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003105 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003107 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303108 log.Fields{
3109 "newinport": actionInfo[Output].(uint32),
3110 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303112 return olterrors.NewErrNotFound("nni-port",
3113 log.Fields{
3114 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3115 "in-port": classifierInfo[InPort].(uint32),
3116 "out-port": actionInfo[Output].(uint32),
3117 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 }
3119 }
3120 }
3121 return nil
3122}
Gamze Abakafee36392019-10-03 11:17:24 +00003123
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003125 /* Metadata 8 bytes:
3126 Most Significant 2 Bytes = Inner VLAN
3127 Next 2 Bytes = Tech Profile ID(TPID)
3128 Least Significant 4 Bytes = Port ID
3129 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3130 subscriber related flows.
3131 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003132 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003133 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003134 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003135 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003136 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003137 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003138}
3139
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003140func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3141 for _, sliceElement := range slice {
3142 if sliceElement == item {
3143 return slice
3144 }
3145 }
3146 return append(slice, item)
3147}
3148
3149func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003150 for _, sliceElement := range slice {
3151 if sliceElement == item {
3152 return slice
3153 }
3154 }
3155 return append(slice, item)
3156}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303157
3158// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003159func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303160
3161 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3162 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003164 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003166 log.Fields{
3167 "port-number": action[Output].(uint32),
3168 "error": err})
3169 return uint32(0), err
3170 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303172 return intfID, nil
3173 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003174 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003175 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003177 log.Fields{
3178 "port-number": action[Output].(uint32),
3179 "error": err})
3180 return uint32(0), err
3181 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003182 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303183 return intfID, nil
3184 }
3185 return uint32(0), nil
3186}
3187
3188// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003189func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3190 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3191 if err != nil {
3192 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3193 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3194 return
3195 }
3196 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003197
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003198 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003199 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003200 f.packetInGemPortLock.RUnlock()
3201
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303202 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003203 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003204 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 +05303205 log.Fields{
3206 "pktinkey": pktInkey,
3207 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003208 return
3209 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303210 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003211 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003212 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003214
npujarec5762e2020-01-01 14:08:48 +05303215 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216 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 +05303217 log.Fields{
3218 "pktinkey": pktInkey,
3219 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303220}
3221
Esin Karaman7fb80c22020-07-16 14:23:33 +00003222//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3223func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3224 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003225 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003226 return 0, 0, errors.New("invalid packet length")
3227 }
3228 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3229 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3230
3231 var index int8
3232 if outerEthType == 0x8100 {
3233 if innerEthType == 0x8100 {
3234 // q-in-q 802.1ad or 802.1q double tagged packet.
3235 // get the inner vlanId
3236 index = 18
3237 } else {
3238 index = 14
3239 }
3240 priority := (packet[index] >> 5) & 0x7
3241 //13 bits composes vlanId value
3242 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3243 return vlan, priority, nil
3244 }
3245 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3246 return 0, 0, nil
3247}
3248
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303249// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303250func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003251
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003252 f.onuGemInfoLock.Lock()
3253 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003255 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303256 for idx, onu := range onugem {
3257 if onu.OnuID == onuID {
3258 for _, uni := range onu.UniPorts {
3259 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003260 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 +05303261 return
3262 }
3263 }
3264 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003265 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303266 }
3267 }
npujarec5762e2020-01-01 14:08:48 +05303268 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003269
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303270}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303271
npujarec5762e2020-01-01 14:08:48 +05303272func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3273 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303274 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003275 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303276 return
3277 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003278 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303279 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003280 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303281 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003282 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303283}
Esin Karamanccb714b2019-11-29 15:02:06 +00003284
Girish Gowdra9602eb42020-09-09 15:50:39 -07003285//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3286// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003287func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003288 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003289 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003290 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3291 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3292
Esin Karamanccb714b2019-11-29 15:02:06 +00003293 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003294 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 -07003295 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003296 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003297
3298 var onuID = int32(NoneOnuID)
3299 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003300 var flowID uint64
3301 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3302 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3303 log.Fields{
3304 "flow": flow,
3305 "device-id": f.deviceHandler.device.Id,
3306 "intf-id": networkInterfaceID,
3307 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003308 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003309 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3310 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3311 log.Fields{
3312 "flow": flowInfo.Flow,
3313 "flow-id": flow.Id,
3314 "device-id": f.deviceHandler.device.Id})
3315 // Remove from device
3316 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3317 // DKB
3318 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3319 log.Fields{
3320 "flow-id": flow.Id,
3321 "error": err})
3322 return err
3323 }
3324 // Remove flow from KV store
3325 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00003326}
3327
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3329func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3330 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3331 if err != nil {
3332 _ = olterrors.NewErrNotFound("onu", log.Fields{
3333 "pon-port": f.ponPortIdx}, err).Log()
3334 return
3335 }
3336
3337 f.subscriberDataPathFlowIDMapLock.Lock()
3338 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3339
3340 for _, onu := range onuGemInfo {
3341 for _, uniID := range onu.UniPorts {
3342 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3343 if err != nil {
3344 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3345 }
3346 for _, flowID := range flowIDs {
3347 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3348 if flowInfo == nil {
3349 // Error is already logged in the called function
3350 continue
3351 }
3352 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3353 flowInfo.Flow.FlowType == Downstream &&
3354 flowInfo.Flow.Classifier.OVid > 0 &&
3355 flowInfo.Flow.TechProfileId > 0 {
3356 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3357 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3358 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3359 }
3360 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3361 flowInfo.Flow.FlowType == Upstream &&
3362 flowInfo.Flow.Action.OVid > 0 &&
3363 flowInfo.Flow.TechProfileId > 0 {
3364 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3365 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3366 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3367 }
3368 }
3369 }
3370 }
3371 }
3372}
3373
3374// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3375func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3376 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3377}