blob: 009b43c8374483e61884b85014f1d3beba751ca2 [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"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070025 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
26 "github.com/opencord/voltha-lib-go/v4/pkg/log"
27 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080028 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070029 "github.com/opencord/voltha-protos/v4/go/common"
30 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
31 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
32 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
33 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
34 "github.com/opencord/voltha-protos/v4/go/voltha"
Girish Gowdra9602eb42020-09-09 15:50:39 -070035 "strings"
36 "sync"
Chaitrashree G S579fe732019-08-20 20:50:47 -040037
Thomas Lee S94109f12020-03-03 16:39:29 +053038 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000039 "google.golang.org/grpc/codes"
40 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053041)
42
43const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070044 //IPProtoDhcp flow category
45 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053046
Girish Gowdraa09aeab2020-09-14 16:30:52 -070047 //IgmpProto proto value
48 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070049
50 //EapEthType eapethtype value
51 EapEthType = 0x888e
52 //LldpEthType lldp ethtype value
53 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000054 //IPv4EthType IPv4 ethernet type value
55 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070056
Andrea Campanella7acc0b92020-02-14 09:20:49 +010057 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
58 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040059
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070060 //DefaultMgmtVlan default vlan value
61 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053062
manikkaraj kbf256be2019-03-25 00:13:48 +053063 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
David K. Bainbridge82efc492019-09-04 09:57:11 -070065 //Upstream constant
66 Upstream = "upstream"
67 //Downstream constant
68 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000069 //Multicast constant
70 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070071 //PacketTagType constant
72 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Untagged constant
74 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070075 //SingleTag constant
76 SingleTag = "single_tag"
77 //DoubleTag constant
78 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053079
80 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070081
82 //EthType constant
83 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000084 //EthDst constant
85 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 //TPID constant
87 TPID = "tpid"
88 //IPProto constant
89 IPProto = "ip_proto"
90 //InPort constant
91 InPort = "in_port"
92 //VlanVid constant
93 VlanVid = "vlan_vid"
94 //VlanPcp constant
95 VlanPcp = "vlan_pcp"
96
97 //UDPDst constant
98 UDPDst = "udp_dst"
99 //UDPSrc constant
100 UDPSrc = "udp_src"
101 //Ipv4Dst constant
102 Ipv4Dst = "ipv4_dst"
103 //Ipv4Src constant
104 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700105 //Metadata constant
106 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700107 //TunnelID constant
108 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700109 //Output constant
110 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000111 //GroupID constant
112 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700113 // Actions
114
115 //PopVlan constant
116 PopVlan = "pop_vlan"
117 //PushVlan constant
118 PushVlan = "push_vlan"
119 //TrapToHost constant
120 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400121 //MaxMeterBand constant
122 MaxMeterBand = 2
123 //VlanPCPMask contant
124 VlanPCPMask = 0xFF
125 //VlanvIDMask constant
126 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000127 //IntfID constant
128 IntfID = "intfId"
129 //OnuID constant
130 OnuID = "onuId"
131 //UniID constant
132 UniID = "uniId"
133 //PortNo constant
134 PortNo = "portNo"
135 //AllocID constant
136 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000137
138 //NoneOnuID constant
139 NoneOnuID = -1
140 //NoneUniID constant
141 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700142
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700143 // Max number of flows that can be queued per ONU
144 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530145
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700146 bitMapPrefix = "0b"
147 pbit1 = '1'
148)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400149
Gamze Abakafee36392019-10-03 11:17:24 +0000150type schedQueue struct {
151 direction tp_pb.Direction
152 intfID uint32
153 onuID uint32
154 uniID uint32
155 tpID uint32
156 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700157 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000158 meterID uint32
159 flowMetadata *voltha.FlowMetadata
160}
161
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700162// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
163type subscriberDataPathFlowIDKey struct {
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 direction string
168 tpID uint32
169}
170
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700171// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
172// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
173// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
174// flow and processes it serially
175type flowControlBlock struct {
176 ctx context.Context // Flow handler context
177 addFlow bool // if true flow to be added, else removed
178 flow *voltha.OfpFlowStats // Flow message
179 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
180 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000181}
182
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700183//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530184type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700185 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
186 techprofile map[uint32]tp.TechProfileIf
187 deviceHandler *DeviceHandler
188 grpMgr *OpenOltGroupMgr
189 resourceMgr *rsrcMgr.OpenOltResourceMgr
190
191 onuIdsLock sync.RWMutex // TODO: Do we need this?
192
193 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
194 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
195
196 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
197 packetInGemPortLock sync.RWMutex
198
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700199 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700200 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700201 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700202 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700204 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
205 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
206 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
207 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700208
209 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
210 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
211 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530212}
213
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700214//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700215func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000216 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530217 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530218 var err error
219 var idx uint32
220
manikkaraj kbf256be2019-03-25 00:13:48 +0530221 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700222 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530223 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000224 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000225 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
226 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530227 return nil
228 }
William Kurkian740a09c2019-10-23 17:07:38 -0400229 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700230 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700232 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700233 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700234 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
235 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700236
237 // Create a slice of buffered channels for handling concurrent flows per ONU.
238 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
239 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
240 for i := range flowMgr.incomingFlows {
241 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
242 // Spin up a go routine to handling incoming flows (add/remove).
243 // There will be on go routine per ONU.
244 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
245 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
246 }
247
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530248 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700249 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
250 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530251 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700252 //Load flowID list per gem map per interface from the kvstore.
253 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000254 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700255 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700256 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000257 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530258 return &flowMgr
259}
260
Kent Hagermane6ff1012020-07-14 15:07:53 -0400261func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
263 // Flow is not replicated in this case, we need to register the flow for a single gem-port
264 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
265 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
266 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
267 for _, gemPort := range deviceFlow.PbitToGemport {
268 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
269 return err
270 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700271 }
Gamze Abakafee36392019-10-03 11:17:24 +0000272 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700273 return nil
274}
275
276func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
277 f.flowsUsedByGemPortKey.Lock()
278 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
279 if !ok {
280 flowIDList = []uint64{flowFromCore.Id}
281 }
282 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
283 f.flowsUsedByGemPort[gemPortID] = flowIDList
284 f.flowsUsedByGemPortKey.Unlock()
285
286 // update the flowids for a gem to the KVstore
287 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400288}
289
Girish Gowdra9602eb42020-09-09 15:50:39 -0700290func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000291 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200292 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000293 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530294 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700295 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530296
Neha Sharma96b7bf22020-06-15 10:37:32 +0000297 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530298 "device-id": f.deviceHandler.device.Id,
299 "intf-id": intfID,
300 "onu-id": onuID,
301 "uni-id": uniID,
302 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700303 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530304 "action": actionInfo,
305 "usmeter-iD": UsMeterID,
306 "dsmeter-iD": DsMeterID,
307 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400308 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
309 // is because the flow is an NNI flow and there would be no onu resources associated with it
310 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400311 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200312 cause := "no-onu-id-for-flow"
313 fields := log.Fields{
314 "onu": onuID,
315 "port-no": portNo,
316 "classifer": classifierInfo,
317 "action": actionInfo,
318 "device-id": f.deviceHandler.device.Id}
319 logger.Errorw(ctx, cause, fields)
320 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530321 }
322
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700323 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000324 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530325 "uni": uni,
326 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530327
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700328 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
329 "device-id": f.deviceHandler.device.Id,
330 "intf-id": intfID,
331 "onu-id": onuID,
332 "uni-id": uniID,
333 "port-no": portNo,
334 "classifier": classifierInfo,
335 "action": actionInfo,
336 "usmeter-id": UsMeterID,
337 "dsmeter-id": DsMeterID,
338 "tp-id": TpID})
339 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
340 if allocID == 0 || gemPorts == nil || TpInst == nil {
341 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
342 return olterrors.NewErrNotFound(
343 "alloc-id-gem-ports-tp-unavailable",
344 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400345 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700346 args := make(map[string]uint32)
347 args[IntfID] = intfID
348 args[OnuID] = onuID
349 args[UniID] = uniID
350 args[PortNo] = portNo
351 args[AllocID] = allocID
352
353 /* Flows can be added specific to gemport if p-bits are received.
354 * If no pbit mentioned then adding flows for all gemports
355 */
356 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
357
Andrea Campanellabfe08432020-09-11 17:07:03 +0200358 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530359}
360
salmansiddiqui7ac62132019-08-22 03:58:50 +0000361// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530362func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363
Neha Sharma96b7bf22020-06-15 10:37:32 +0000364 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530365 log.Fields{"dir": sq.direction,
366 "intf-id": sq.intfID,
367 "onu-id": sq.onuID,
368 "uni-id": sq.uniID,
369 "tp-id": sq.tpID,
370 "meter-id": sq.meterID,
371 "tp-inst": sq.tpInst,
372 "flowmetadata": sq.flowMetadata,
373 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374
Gamze Abakafee36392019-10-03 11:17:24 +0000375 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000376 if err != nil {
377 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400378 }
379
380 /* Lets make a simple assumption that if the meter-id is present on the KV store,
381 * then the scheduler and queues configuration is applied on the OLT device
382 * in the given direction.
383 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000384
Manikkaraj kb1d51442019-07-23 10:41:02 -0400385 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530386 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530388 return olterrors.NewErrNotFound("meter",
389 log.Fields{"intf-id": sq.intfID,
390 "onu-id": sq.onuID,
391 "uni-id": sq.uniID,
392 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000394
Manikkaraj kb1d51442019-07-23 10:41:02 -0400395 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000396 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000397 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530400 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800401 "unsupported": "meter-id",
402 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530403 "meter-id-in-flow": sq.meterID,
404 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400405 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000406
Neha Sharma96b7bf22020-06-15 10:37:32 +0000407 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530408 log.Fields{
409 "meter-id": sq.meterID,
410 "direction": Direction,
411 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000412
Gamze Abakafee36392019-10-03 11:17:24 +0000413 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000414 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000415 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000416 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000418
419 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530420 return olterrors.NewErrNotFound("scheduler-config",
421 log.Fields{
422 "intf-id": sq.intfID,
423 "direction": sq.direction,
424 "tp-inst": sq.tpInst,
425 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000426 }
427
Manikkaraj kb1d51442019-07-23 10:41:02 -0400428 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000429 if sq.flowMetadata != nil {
430 for _, meter := range sq.flowMetadata.Meters {
431 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530434 log.Fields{"meterConfig": meterConfig,
435 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400436 break
437 }
438 }
439 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400441 }
442 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530443 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800444 "reason": "Could-not-get-meterbands-from-flowMetadata",
445 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "meter-id": sq.meterID,
447 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400448 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530450 log.Fields{"Bands": meterConfig.Bands,
451 "meter-id": sq.meterID,
452 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530453 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800454 "reason": "Invalid-number-of-bands-in-meter",
455 "meterband-count": len(meterConfig.Bands),
456 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530457 "meter-id": sq.meterID,
458 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 }
460 cir := meterConfig.Bands[0].Rate
461 cbs := meterConfig.Bands[0].BurstSize
462 eir := meterConfig.Bands[1].Rate
463 ebs := meterConfig.Bands[1].BurstSize
464 pir := cir + eir
465 pbs := cbs + ebs
466 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
467
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700468 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000469 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700471 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530472 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
473 log.Fields{"intf-id": sq.intfID,
474 "direction": sq.direction,
475 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
477
salmansiddiqui7ac62132019-08-22 03:58:50 +0000478 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 * store the meter id on the KV store, for further reference.
480 */
npujarec5762e2020-01-01 14:08:48 +0530481 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 +0530482 return olterrors.NewErrAdapter("failed-updating-meter-id",
483 log.Fields{"onu-id": sq.onuID,
484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000487 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530488 log.Fields{"direction": Direction,
489 "Meter": meterConfig,
490 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 return nil
492}
493
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700494func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000495 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000496
497 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530498 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
499 log.Fields{"intf-id": sq.intfID,
500 "direction": sq.direction,
501 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000502 }
503
Neha Sharma96b7bf22020-06-15 10:37:32 +0000504 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530505 log.Fields{
506 "direction": sq.direction,
507 "TrafficScheds": TrafficSched,
508 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530509 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000510 IntfId: sq.intfID, OnuId: sq.onuID,
511 UniId: sq.uniID, PortNo: sq.uniPort,
512 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000513 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000514 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000515 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530516 "direction": sq.direction,
517 "traffic-queues": trafficQueues,
518 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000519
520 // On receiving the CreateTrafficQueues request, the driver should create corresponding
521 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000522 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530523 log.Fields{"direction": sq.direction,
524 "traffic-queues": trafficQueues,
525 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530526 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000527 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
528 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000529 TrafficQueues: trafficQueues,
530 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530531 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000532 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000533 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530534 "direction": sq.direction,
535 "traffic-queues": trafficQueues,
536 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537
Esin Karamanccb714b2019-11-29 15:02:06 +0000538 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000539 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000540 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700541 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000542 //assumed that there is only one queue per PON for the multicast service
543 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
544 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000545 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000546 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700547 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000548 gemPortID: multicastQueuePerPonPort.GemportId,
549 servicePriority: multicastQueuePerPonPort.Priority,
550 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700551 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000552 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400553 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
554 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
555 return err
556 }
Shrey Baid26912972020-04-16 21:02:31 +0530557
Neha Sharma96b7bf22020-06-15 10:37:32 +0000558 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000559 }
560 }
561 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000562 return nil
563}
564
salmansiddiqui7ac62132019-08-22 03:58:50 +0000565// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530566func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400567
568 var Direction string
569 var SchedCfg *tp_pb.SchedulerConfig
570 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000571 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530572 log.Fields{
573 "direction": sq.direction,
574 "intf-id": sq.intfID,
575 "onu-id": sq.onuID,
576 "uni-id": sq.uniID,
577 "uni-port": sq.uniPort,
578 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000579 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400581 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000582 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000583 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400584 Direction = "downstream"
585 }
586
Girish Kumar8f73fe02019-12-09 13:19:37 +0000587 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530588 return olterrors.NewErrNotFound("scheduler-config",
589 log.Fields{
590 "int-id": sq.intfID,
591 "direction": sq.direction,
592 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000593 }
594
npujarec5762e2020-01-01 14:08:48 +0530595 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400596 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530597 return olterrors.NewErrNotFound("meter",
598 log.Fields{
599 "onu-id": sq.onuID,
600 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400601 }
602 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000603 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530604 log.Fields{
605 "direction": Direction,
606 "intf-id": sq.intfID,
607 "onu-id": sq.onuID,
608 "uni-id": sq.uniID,
609 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400610 return nil
611 }
612 cir := KVStoreMeter.Bands[0].Rate
613 cbs := KVStoreMeter.Bands[0].BurstSize
614 eir := KVStoreMeter.Bands[1].Rate
615 ebs := KVStoreMeter.Bands[1].BurstSize
616 pir := cir + eir
617 pbs := cbs + ebs
618
619 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
620
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700621 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000622 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000623
Neha Sharma96b7bf22020-06-15 10:37:32 +0000624 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530626 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
627 log.Fields{
628 "intf-id": sq.intfID,
629 "direction": sq.direction,
630 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000631 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400632
npujarec5762e2020-01-01 14:08:48 +0530633 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000634 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
635 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000636 TrafficQueues: TrafficQueues,
637 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000638 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530639 log.Fields{
640 "intf-id": sq.intfID,
641 "traffic-queues": TrafficQueues,
642 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400643 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000644 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530645 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000646 IntfId: sq.intfID, OnuId: sq.onuID,
647 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000649 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530650 log.Fields{
651 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700652 "traffic-schedulers": TrafficSched,
653 "onu-id": sq.onuID,
654 "uni-id": sq.uniID,
655 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400656 }
657
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700658 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
659 log.Fields{"device-id": f.deviceHandler.device.Id,
660 "intf-id": sq.intfID,
661 "onu-id": sq.onuID,
662 "uni-id": sq.uniID,
663 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000664
665 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400666 * delete the meter id on the KV store.
667 */
npujarec5762e2020-01-01 14:08:48 +0530668 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400669 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530670 return olterrors.NewErrAdapter("unable-to-remove-meter",
671 log.Fields{
672 "onu": sq.onuID,
673 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700674 "device-id": f.deviceHandler.device.Id,
675 "intf-id": sq.intfID,
676 "onu-id": sq.onuID,
677 "uni-id": sq.uniID,
678 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000680 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530681 log.Fields{
682 "meter-id": KVStoreMeter.MeterId,
683 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700684 "device-id": f.deviceHandler.device.Id,
685 "intf-id": sq.intfID,
686 "onu-id": sq.onuID,
687 "uni-id": sq.uniID,
688 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400689 return err
690}
691
Gamze Abakafee36392019-10-03 11:17:24 +0000692// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700693func (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 +0000694 var allocIDs []uint32
695 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530696 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530697 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000698 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000699
npujarec5762e2020-01-01 14:08:48 +0530700 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
701 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000702 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530703
Neha Sharma96b7bf22020-06-15 10:37:32 +0000704 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530705 "intf-id": intfID,
706 "onu-id": onuID,
707 "uni-id": uniID,
708 "device-id": f.deviceHandler.device.Id,
709 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530710
Manikkaraj kb1d51442019-07-23 10:41:02 -0400711 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530712 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000713 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000714 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530715 log.Fields{
716 "path": tpPath,
717 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530718 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000719 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530720 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000721 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530722 log.Fields{
723 "error": err,
724 "tp-id": TpID,
725 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000726 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530727 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400728 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
729 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
730 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530731 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000732 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530733 log.Fields{
734 "uni": uni,
735 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530736 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530737 }
Gamze Abakafee36392019-10-03 11:17:24 +0000738
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700739 switch tpInst := techProfileInstance.(type) {
740 case *tp.TechProfile:
741 if UsMeterID != 0 {
742 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
743 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
744 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000745 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700746 log.Fields{
747 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700748 "onu-id": onuID,
749 "uni-id": uniID,
750 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700751 "meter-id": UsMeterID,
752 "device-id": f.deviceHandler.device.Id})
753 return 0, nil, nil
754 }
755 }
756 if DsMeterID != 0 {
757 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
758 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
759 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700761 log.Fields{
762 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700763 "onu-id": onuID,
764 "uni-id": uniID,
765 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700766 "meter-id": DsMeterID,
767 "device-id": f.deviceHandler.device.Id})
768 return 0, nil, nil
769 }
770 }
771 allocID := tpInst.UsScheduler.AllocID
772 for _, gem := range tpInst.UpstreamGemPortAttributeList {
773 gemPortIDs = append(gemPortIDs, gem.GemportID)
774 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700775 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000776
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700777 if tpInstanceExists {
778 return allocID, gemPortIDs, techProfileInstance
779 }
780
781 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700782 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700783 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000784 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700785 log.Fields{
786 "alloc-ids": allocIDs,
787 "gemports": allgemPortIDs,
788 "device-id": f.deviceHandler.device.Id})
789 // Send Tconts and GEM ports to KV store
790 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530791 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700792 case *tp.EponProfile:
793 // CreateSchedulerQueues for EPON needs to be implemented here
794 // when voltha-protos for EPON is completed.
795 allocID := tpInst.AllocID
796 for _, gem := range tpInst.UpstreamQueueAttributeList {
797 gemPortIDs = append(gemPortIDs, gem.GemportID)
798 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700799 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700800
801 if tpInstanceExists {
802 return allocID, gemPortIDs, techProfileInstance
803 }
804
805 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700806 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700807 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700809 log.Fields{
810 "alloc-ids": allocIDs,
811 "gemports": allgemPortIDs,
812 "device-id": f.deviceHandler.device.Id})
813 // Send Tconts and GEM ports to KV store
814 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
815 return allocID, gemPortIDs, techProfileInstance
816 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000817 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700818 log.Fields{
819 "tpInst": tpInst})
820 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530821 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530822}
823
npujarec5762e2020-01-01 14:08:48 +0530824func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530825
Neha Sharma96b7bf22020-06-15 10:37:32 +0000826 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530827 log.Fields{
828 "intf-id": intfID,
829 "onu-id": onuID,
830 "uni-id": uniID,
831 "alloc-id": allocID,
832 "gemport-ids": gemPortIDs,
833 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530834 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530835 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 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 +0530837 }
npujarec5762e2020-01-01 14:08:48 +0530838 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000839 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 +0530840 }
npujarec5762e2020-01-01 14:08:48 +0530841 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530843 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000844 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 -0400845 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530846 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400847 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530848}
849
Neha Sharma96b7bf22020-06-15 10:37:32 +0000850func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000851 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530852 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000853 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700854 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400855 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530857 log.Fields{
858 "intf-id": intfID,
859 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530860 }
861 }
862 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400863 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530864 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530865 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800866 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530867 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
868 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530871 log.Fields{
872 "numofTech": tpCount,
873 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
874 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 return nil
876}
877
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700878func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530879 portNo uint32, uplinkClassifier map[string]interface{},
880 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700881 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700882 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000883 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530884 log.Fields{
885 "uplinkClassifier": uplinkClassifier,
886 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700887 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
888 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530889 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530890}
891
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700892func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530893 portNo uint32, downlinkClassifier map[string]interface{},
894 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700895 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700896 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000897 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530898 log.Fields{
899 "downlinkClassifier": downlinkClassifier,
900 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400901 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
902 if vlan, exists := downlinkClassifier[VlanVid]; exists {
903 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700904 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
906 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530907 log.Fields{
908 "flow": logicalFlow,
909 "device-id": f.deviceHandler.device.Id,
910 "onu-id": onuID,
911 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800912 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400913 }
914 }
915 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530916 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400917
Manikkaraj k884c1242019-04-11 16:26:42 +0530918 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700919 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400920 // vlan_vid is a uint32. must be type asserted as such or conversion fails
921 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530922 if ok {
923 downlinkAction[VlanVid] = dlClVid & 0xfff
924 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530925 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530926 "reason": "failed-to-convert-vlanid-classifier",
927 "vlan-id": VlanVid,
928 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530929 }
930
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700931 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
932 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530933}
934
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700935func (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 +0530936 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700937 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
938
939 var inverseDirection string
940 if direction == Upstream {
941 inverseDirection = Downstream
942 } else {
943 inverseDirection = Upstream
944 }
945
Neha Sharma96b7bf22020-06-15 10:37:32 +0000946 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530947 log.Fields{
948 "intf-id": intfID,
949 "onu-id": onuID,
950 "uni-id": uniID,
951 "device-id": f.deviceHandler.device.Id,
952 "classifier": classifier,
953 "action": action,
954 "direction": direction,
955 "alloc-id": allocID,
956 "gemport-id": gemPortID,
957 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700958
959 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530961 log.Fields{
962 "device-id": f.deviceHandler.device.Id,
963 "intf-id": intfID,
964 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800965 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530966 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 classifierProto, err := makeOpenOltClassifierField(classifier)
968 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530969 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530970 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530972 log.Fields{
973 "classifier": *classifierProto,
974 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000975 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800976 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530977 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530978 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000979 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530980 log.Fields{
981 "action": *actionProto,
982 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000983 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530984 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530985 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800986 log.Fields{
987 "classifier": classifier,
988 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530989 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800990 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530991 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700992
993 // Get symmetric flowID if it exists
994 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
995 // symmetric flow earlier
996 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
997 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
998 f.subscriberDataPathFlowIDMapLock.RLock()
999 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1000 f.subscriberDataPathFlowIDMapLock.RUnlock()
1001
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001002 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001003 OnuId: int32(onuID),
1004 UniId: int32(uniID),
1005 FlowId: logicalFlow.Id,
1006 FlowType: direction,
1007 AllocId: int32(allocID),
1008 NetworkIntfId: int32(networkIntfID),
1009 GemportId: int32(gemPortID),
1010 Classifier: classifierProto,
1011 Action: actionProto,
1012 Priority: int32(logicalFlow.Priority),
1013 Cookie: logicalFlow.Cookie,
1014 PortNo: portNo,
1015 TechProfileId: tpID,
1016 ReplicateFlow: len(pbitToGem) > 0,
1017 PbitToGemport: pbitToGem,
1018 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001019 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001020 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001021 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301022 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301024 log.Fields{"direction": direction,
1025 "device-id": f.deviceHandler.device.Id,
1026 "flow": flow,
1027 "intf-id": intfID,
1028 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001029 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1030 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1031 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301032 log.Fields{
1033 "flow": flow,
1034 "device-id": f.deviceHandler.device.Id,
1035 "intf-id": intfID,
1036 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001037 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001038
1039 // Update the current flowID to the map
1040 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1041 f.subscriberDataPathFlowIDMapLock.Lock()
1042 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1043 f.subscriberDataPathFlowIDMapLock.Unlock()
1044
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301046}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001047
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001048func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1049 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001050 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301051
Neha Sharma96b7bf22020-06-15 10:37:32 +00001052 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301053 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301054 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001055 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301056 "action": action,
1057 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001058 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301059 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301060
1061 // Clear the action map
1062 for k := range action {
1063 delete(action, k)
1064 }
1065
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001066 action[TrapToHost] = true
1067 classifier[UDPSrc] = uint32(68)
1068 classifier[UDPDst] = uint32(67)
1069 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301070
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001071 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001072 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301073 log.Fields{
1074 "device-id": f.deviceHandler.device.Id,
1075 "intf-id": intfID,
1076 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001077 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301078 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301079
Neha Sharma96b7bf22020-06-15 10:37:32 +00001080 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301081 log.Fields{
1082 "ul_classifier": classifier,
1083 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001084 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301085 "intf-id": intfID,
1086 "onu-id": onuID,
1087 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301088
David K. Bainbridge794735f2020-02-11 21:01:37 -08001089 classifierProto, err := makeOpenOltClassifierField(classifier)
1090 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301091 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301092 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001094 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301096 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301097 }
1098
David K. Bainbridge794735f2020-02-11 21:01:37 -08001099 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001100 OnuId: int32(onuID),
1101 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001102 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001103 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001104 AllocId: int32(allocID),
1105 NetworkIntfId: int32(networkIntfID),
1106 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301107 Classifier: classifierProto,
1108 Action: actionProto,
1109 Priority: int32(logicalFlow.Priority),
1110 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001111 PortNo: portNo,
1112 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001113 ReplicateFlow: len(pbitToGem) > 0,
1114 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001115 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301120 log.Fields{
1121 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001122 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301123 "intf-id": intfID,
1124 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1126 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 +05301127 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1128 log.Fields{
1129 "flow": dhcpFlow,
1130 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301131 }
1132
David K. Bainbridge794735f2020-02-11 21:01:37 -08001133 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301134}
1135
Esin Karamanae41e2b2019-12-17 18:13:13 +00001136//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301137func (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 -07001138 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1139 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001140}
1141
1142//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301143func (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 -07001144 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 +00001145
Neha Sharma96b7bf22020-06-15 10:37:32 +00001146 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001147 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301148 return olterrors.NewErrNotFound("nni-interface-id",
1149 log.Fields{
1150 "classifier": classifier,
1151 "action": action,
1152 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001153 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001154 }
1155
1156 // Clear the action map
1157 for k := range action {
1158 delete(action, k)
1159 }
1160
1161 action[TrapToHost] = true
1162 classifier[PacketTagType] = SingleTag
1163 delete(classifier, VlanVid)
1164
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001165 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001166 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001167 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001168 }
1169
Neha Sharma96b7bf22020-06-15 10:37:32 +00001170 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301171 log.Fields{
1172 "ul_classifier": classifier,
1173 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001174 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301175 "device-id": f.deviceHandler.device.Id,
1176 "intf-id": intfID,
1177 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001178
David K. Bainbridge794735f2020-02-11 21:01:37 -08001179 classifierProto, err := makeOpenOltClassifierField(classifier)
1180 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301181 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001182 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001183 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301184 log.Fields{
1185 "classifier": *classifierProto,
1186 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001187 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301189 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001190 }
1191
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001193 OnuId: int32(onuID),
1194 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001195 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001196 FlowType: Upstream,
1197 AllocId: int32(allocID),
1198 NetworkIntfId: int32(networkIntfID),
1199 GemportId: int32(gemPortID),
1200 Classifier: classifierProto,
1201 Action: actionProto,
1202 Priority: int32(logicalFlow.Priority),
1203 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001204 PortNo: portNo,
1205 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001206 ReplicateFlow: len(pbitToGem) > 0,
1207 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001208 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001209
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001211 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 -08001212 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001213
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001214 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1215 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 +05301216 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 +00001217 }
1218
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220}
1221
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001223func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1224 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001225 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001226 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301227 log.Fields{
1228 "intf-id": intfID,
1229 "onu-id": onuID,
1230 "port-no": portNo,
1231 "alloc-id": allocID,
1232 "gemport-id": gemPortID,
1233 "vlan-id": vlanID,
1234 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301235
1236 uplinkClassifier := make(map[string]interface{})
1237 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301238
manikkaraj kbf256be2019-03-25 00:13:48 +05301239 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001240 uplinkClassifier[EthType] = uint32(EapEthType)
1241 uplinkClassifier[PacketTagType] = SingleTag
1242 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001243 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301244 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001245 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001246 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001247 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301248 "device-id": f.deviceHandler.device.Id,
1249 "onu-id": onuID,
1250 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301252 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301253 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001254 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301255 log.Fields{
1256 "ul_classifier": uplinkClassifier,
1257 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001258 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301259 "device-id": f.deviceHandler.device.Id,
1260 "intf-id": intfID,
1261 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301262
David K. Bainbridge794735f2020-02-11 21:01:37 -08001263 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1264 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301265 return olterrors.NewErrInvalidValue(log.Fields{
1266 "classifier": uplinkClassifier,
1267 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301268 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001269 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301270 log.Fields{
1271 "classifier": *classifierProto,
1272 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001273 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301275 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301276 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001277 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301278 log.Fields{
1279 "action": *actionProto,
1280 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301282 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301283 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001284 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301285 "action": action,
1286 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301288 }
1289
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001291 OnuId: int32(onuID),
1292 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001293 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001294 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295 AllocId: int32(allocID),
1296 NetworkIntfId: int32(networkIntfID),
1297 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301298 Classifier: classifierProto,
1299 Action: actionProto,
1300 Priority: int32(logicalFlow.Priority),
1301 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001302 PortNo: portNo,
1303 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001304 ReplicateFlow: len(pbitToGem) > 0,
1305 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001306 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001307 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001308 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001309 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001310 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301311 log.Fields{
1312 "device-id": f.deviceHandler.device.Id,
1313 "onu-id": onuID,
1314 "intf-id": intfID,
1315 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001316 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1317 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 +05301318 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1319 log.Fields{
1320 "flow": upstreamFlow,
1321 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301322 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001323 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301324}
1325
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001327 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001328
1329 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1330 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1331 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001332 if vlanID != ReservedVlan {
1333 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001334 classifier.OVid = vid
1335 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301336 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001337 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1338 vid := uint32(metadata)
1339 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001340 classifier.IVid = vid
1341 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301342 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301343 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001344 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301345 classifier.OPbits = vlanPcp
1346 } else {
1347 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301348 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001349 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1350 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1351 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1352 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001353 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001354 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1355 classifier.PktTagType = pktTagType
1356
1357 switch pktTagType {
1358 case SingleTag:
1359 case DoubleTag:
1360 case Untagged:
1361 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001362 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301363 }
1364 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301366}
1367
Gamze Abaka724d0852020-03-18 12:10:24 +00001368func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 var actionCmd openoltpb2.ActionCmd
1370 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301371 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301373 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001374 if _, ok := actionInfo[VlanPcp]; ok {
1375 action.Cmd.RemarkInnerPbits = true
1376 action.IPbits = actionInfo[VlanPcp].(uint32)
1377 if _, ok := actionInfo[VlanVid]; ok {
1378 action.Cmd.TranslateInnerTag = true
1379 action.IVid = actionInfo[VlanVid].(uint32)
1380 }
1381 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382 } else if _, ok := actionInfo[PushVlan]; ok {
1383 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301384 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001385 if _, ok := actionInfo[VlanPcp]; ok {
1386 action.OPbits = actionInfo[VlanPcp].(uint32)
1387 action.Cmd.RemarkOuterPbits = true
1388 if _, ok := classifierInfo[VlanVid]; ok {
1389 action.IVid = classifierInfo[VlanVid].(uint32)
1390 action.Cmd.TranslateInnerTag = true
1391 }
1392 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001393 } else if _, ok := actionInfo[TrapToHost]; ok {
1394 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301395 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001396 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301397 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001398 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301399}
1400
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001401// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001402func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1403 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301404}
1405
Gamze Abakafee36392019-10-03 11:17:24 +00001406// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001407func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301408 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001409 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1410
Gamze Abakafee36392019-10-03 11:17:24 +00001411 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301412 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001413 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301414 // return err
1415 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001416 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001417 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001418 }
1419 return nil
1420}
1421
1422// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301423func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001424 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001425 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001426 }
npujarec5762e2020-01-01 14:08:48 +05301427 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301428 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1429 log.Fields{
1430 "tp-id": tpID,
1431 "uni-port-name": uniPortName,
1432 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001433 }
1434 return nil
1435}
1436
David K. Bainbridge794735f2020-02-11 21:01:37 -08001437func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001438
1439 var intfID uint32
1440 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1441 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1442 */
1443 if deviceFlow.AccessIntfId != -1 {
1444 intfID = uint32(deviceFlow.AccessIntfId)
1445 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001446 // We need to log the valid interface ID.
1447 // 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 +00001448 intfID = uint32(deviceFlow.NetworkIntfId)
1449 }
1450
Neha Sharma96b7bf22020-06-15 10:37:32 +00001451 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301452 "flow": *deviceFlow,
1453 "device-id": f.deviceHandler.device.Id,
1454 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001455 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001456
1457 st, _ := status.FromError(err)
1458 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001459 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001460 "err": err,
1461 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301462 "device-id": f.deviceHandler.device.Id,
1463 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001464 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301465 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001466
1467 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001468 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301469 log.Fields{"err": err,
1470 "device-flow": deviceFlow,
1471 "device-id": f.deviceHandler.device.Id,
1472 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001473 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001475 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301476 log.Fields{
1477 "flow": *deviceFlow,
1478 "device-id": f.deviceHandler.device.Id,
1479 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001480
1481 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1482 if deviceFlow.AccessIntfId != -1 {
1483 // No need to register the flow if it is a trap on nni flow.
1484 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1485 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1486 return err
1487 }
1488 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001489 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001490}
1491
Neha Sharma96b7bf22020-06-15 10:37:32 +00001492func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1493 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301494 log.Fields{
1495 "flow": *deviceFlow,
1496 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001497 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001498 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001499 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001500 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301501 log.Fields{
1502 "err": err,
1503 "deviceFlow": deviceFlow,
1504 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001505 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001506 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001507 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001508 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001509
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001510 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001511 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001512 "of-flow-id": ofFlowID,
1513 "flow": *deviceFlow,
1514 "device-id": f.deviceHandler.device.Id,
1515 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301517}
1518
David K. Bainbridge794735f2020-02-11 21:01:37 -08001519func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001520
1521 classifierInfo := make(map[string]interface{})
1522 actionInfo := make(map[string]interface{})
1523
1524 classifierInfo[EthType] = uint32(LldpEthType)
1525 classifierInfo[PacketTagType] = Untagged
1526 actionInfo[TrapToHost] = true
1527
1528 // LLDP flow is installed to trap LLDP packets on the NNI port.
1529 // We manage flow_id resource pool on per PON port basis.
1530 // Since this situation is tricky, as a hack, we pass the NNI port
1531 // index (network_intf_id) as PON port Index for the flow_id resource
1532 // pool. Also, there is no ONU Id available for trapping LLDP packets
1533 // on NNI port, use onu_id as -1 (invalid)
1534 // ****************** CAVEAT *******************
1535 // This logic works if the NNI Port Id falls within the same valid
1536 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1537 // we need to have a re-look at this.
1538 // *********************************************
1539
1540 var onuID = -1
1541 var uniID = -1
1542 var gemPortID = -1
1543
Neha Sharma96b7bf22020-06-15 10:37:32 +00001544 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001545 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301546 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001547 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001548 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001549 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001550 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001551 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001552
David K. Bainbridge794735f2020-02-11 21:01:37 -08001553 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1554 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301555 return olterrors.NewErrInvalidValue(
1556 log.Fields{
1557 "classifier": classifierInfo,
1558 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001559 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001560 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301561 log.Fields{
1562 "classifier": *classifierProto,
1563 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001564 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301566 return olterrors.NewErrInvalidValue(
1567 log.Fields{
1568 "action": actionInfo,
1569 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001571 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301572 log.Fields{
1573 "action": *actionProto,
1574 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001575
1576 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1577 OnuId: int32(onuID), // OnuId not required
1578 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001579 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001580 FlowType: Downstream,
1581 NetworkIntfId: int32(networkInterfaceID),
1582 GemportId: int32(gemPortID),
1583 Classifier: classifierProto,
1584 Action: actionProto,
1585 Priority: int32(flow.Priority),
1586 Cookie: flow.Cookie,
1587 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001588 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001589 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301590 log.Fields{
1591 "flow": downstreamflow,
1592 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001593 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001594 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301595 log.Fields{
1596 "device-id": f.deviceHandler.device.Id,
1597 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001598 "flow-id": flow.Id})
1599 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1600 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1601 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301602 log.Fields{
1603 "flow": downstreamflow,
1604 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 }
1606 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301607}
1608
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001609func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1610 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001611}
1612
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001613//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001615 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1616 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1617 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301619 log.Fields{
1620 "intf-id": intfID,
1621 "onu-id": onuID,
1622 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001623 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001624 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301625 return nil, olterrors.NewErrNotFound("onu-child-device",
1626 log.Fields{
1627 "onu-id": onuID,
1628 "intf-id": intfID,
1629 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001630 }
1631 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1632 //better to ad the device to cache here.
1633 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1634 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001635 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301636 log.Fields{
1637 "intf-id": intfID,
1638 "onu-id": onuID,
1639 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001640 }
1641
1642 return onuDev.(*OnuDevice), nil
1643}
1644
1645//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001646func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1647 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301648 log.Fields{
1649 "pon-port": intfID,
1650 "onu-id": onuID,
1651 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001652 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001654 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301655 return nil, olterrors.NewErrNotFound("onu",
1656 log.Fields{
1657 "interface-id": parentPortNo,
1658 "onu-id": onuID,
1659 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001660 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301661 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001662 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "device-id": f.deviceHandler.device.Id,
1665 "child_device_id": onuDevice.Id,
1666 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301667 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301668}
1669
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1671 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301672 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "intf-id": intfID,
1676 "onu-id": onuID,
1677 "uni-id": uniID,
1678 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001679 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301680 }
1681
1682 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301684 log.Fields{
1685 "msg": *delGemPortMsg,
1686 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001687 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301688 delGemPortMsg,
1689 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301690 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001691 onuDev.deviceType,
1692 onuDev.deviceID,
1693 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301694 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1695 log.Fields{
1696 "from-adapter": f.deviceHandler.device.Type,
1697 "to-adapter": onuDev.deviceType,
1698 "onu-id": onuDev.deviceID,
1699 "proxyDeviceID": onuDev.proxyDeviceID,
1700 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301701 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001702 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301703 log.Fields{
1704 "msg": delGemPortMsg,
1705 "from-adapter": f.deviceHandler.device.Type,
1706 "to-adapter": onuDev.deviceType,
1707 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301708 return nil
1709}
1710
Neha Sharma96b7bf22020-06-15 10:37:32 +00001711func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1712 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301713 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001714 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301715 log.Fields{
1716 "intf-id": intfID,
1717 "onu-id": onuID,
1718 "uni-id": uniID,
1719 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001720 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301721 }
1722
1723 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "msg": *delTcontMsg,
1727 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001728 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301729 delTcontMsg,
1730 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05301731 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001732 onuDev.deviceType,
1733 onuDev.deviceID,
1734 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301735 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1736 log.Fields{
1737 "from-adapter": f.deviceHandler.device.Type,
1738 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1739 "proxyDeviceID": onuDev.proxyDeviceID,
1740 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301743 log.Fields{
1744 "msg": delTcontMsg,
1745 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301746 return nil
1747}
1748
Girish Gowdrac3037402020-01-22 20:29:53 +05301749// Once the gemport is released for a given onu, it also has to be cleared from local cache
1750// which was used for deriving the gemport->logicalPortNo during packet-in.
1751// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1752// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001753func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001754
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001755 f.onuGemInfoLock.Lock()
1756 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001757
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301759 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001760 "gem-port-id": gemPortID,
1761 "intf-id": intfID,
1762 "onu-id": onuID,
1763 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001764 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001765
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001766 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001767deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001768 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301769 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001770 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301771 // If the gemport is found, delete it from local cache.
1772 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001773 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1774 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001775 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301776 log.Fields{
1777 "intf-id": intfID,
1778 "onu-id": onuID,
1779 "deletedgemport-id": gemPortID,
1780 "gemports": onu.GemPorts,
1781 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001782 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301783 }
1784 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001785 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301786 }
1787 }
1788}
1789
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301790//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001791// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301792func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001793 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001794
Neha Sharma96b7bf22020-06-15 10:37:32 +00001795 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001796 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301797 return olterrors.NewErrNotFound("tp-id",
1798 log.Fields{
1799 "flow": flow,
1800 "intf": Intf,
1801 "onu-id": onuID,
1802 "uni-id": uniID,
1803 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001804 }
Gamze Abakafee36392019-10-03 11:17:24 +00001805
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001806 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1807 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1808 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1809 log.Fields{
1810 "tpPath": tpPath,
1811 "device-id": f.deviceHandler.device.Id})
1812 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1813 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1814 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1815 log.Fields{
1816 "tp-id": tpID,
1817 "path": tpPath}, err)
1818 }
1819
1820 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1821
1822 if used {
1823 f.flowsUsedByGemPortKey.Lock()
1824 defer f.flowsUsedByGemPortKey.Unlock()
1825
1826 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1827 for i, flowIDinMap := range flowIDs {
1828 if flowIDinMap == flowID {
1829 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1830 // everytime flowsUsedByGemPort cache is updated the same should be updated
1831 // in kv store by calling UpdateFlowIDsForGem
1832 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1833 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1834 return err
1835 }
1836 break
1837 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001838 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001839 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1840 log.Fields{
1841 "gemport-id": gemPortID,
1842 "usedByFlows": flowIDs,
1843 "device-id": f.deviceHandler.device.Id})
1844 return nil
1845 }
1846 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1847 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1848 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1849 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1850 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
1851 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
1852 f.onuIdsLock.Lock() // TODO: What is this lock?
1853
1854 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1855 // by calling DeleteFlowIDsForGem
1856 f.flowsUsedByGemPortKey.Lock()
1857 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1858 f.flowsUsedByGemPortKey.Unlock()
1859 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1860 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1861
1862 f.onuIdsLock.Unlock()
1863
1864 // Delete the gem port on the ONU.
1865 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1866 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1867 log.Fields{
1868 "err": err,
1869 "intf": Intf,
1870 "onu-id": onuID,
1871 "uni-id": uniID,
1872 "device-id": f.deviceHandler.device.Id,
1873 "gemport-id": gemPortID})
1874 }
1875 switch techprofileInst := techprofileInst.(type) {
1876 case *tp.TechProfile:
1877 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1878 if !ok {
1879 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1880 logger.Warn(ctx, err)
1881 }
1882 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1883 logger.Warn(ctx, err)
1884 }
1885 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 {
1886 logger.Warn(ctx, err)
1887 }
1888 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 {
1889 logger.Warn(ctx, err)
1890 }
1891 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1892 // Delete the TCONT on the ONU.
1893 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1894 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1895 log.Fields{
1896 "intf": Intf,
1897 "onu-id": onuID,
1898 "uni-id": uniID,
1899 "device-id": f.deviceHandler.device.Id,
1900 "alloc-id": techprofileInst.UsScheduler.AllocID})
1901 }
1902 }
1903 case *tp.EponProfile:
1904 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1905 logger.Warn(ctx, err)
1906 }
1907 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1908 logger.Warn(ctx, err)
1909 }
1910 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1911 // Delete the TCONT on the ONU.
1912 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1913 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301914 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001915 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301916 "onu-id": onuID,
1917 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001918 "device-id": f.deviceHandler.device.Id,
1919 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001920 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001921 default:
1922 logger.Errorw(ctx, "error-unknown-tech",
1923 log.Fields{
1924 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001925 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301927 return nil
1928}
1929
David K. Bainbridge794735f2020-02-11 21:01:37 -08001930// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001931func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001932 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301934 log.Fields{
1935 "flowDirection": flowDirection,
1936 "flow": *flow,
1937 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001938
1939 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001940 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001941 }
1942
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301943 classifierInfo := make(map[string]interface{})
1944
Neha Sharma96b7bf22020-06-15 10:37:32 +00001945 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301946 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001947 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001948 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301949 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301950
David K. Bainbridge794735f2020-02-11 21:01:37 -08001951 onuID := int32(onu)
1952 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301953
1954 for _, field := range flows.GetOfbFields(flow) {
1955 if field.Type == flows.IP_PROTO {
1956 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001957 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301958 }
1959 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001960 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301961 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001962 "flow-id": flow.Id,
1963 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301964 "onu-id": onuID,
1965 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301966
1967 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1968 onuID = -1
1969 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001970 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1971 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001972 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001973 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001974 log.Fields{
1975 "port-number": inPort,
1976 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001977 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001978 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301979 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001980 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
1981 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})
1982 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
1983 }
1984 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
1985 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
1986 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1987 return err
1988 }
1989 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
1990 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
1991 return err
1992 }
1993 if !flowInfo.Flow.ReplicateFlow {
1994 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
1995 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
1996 "flow-id": flow.Id,
1997 "stored-flow": flowInfo.Flow,
1998 "device-id": f.deviceHandler.device.Id,
1999 "stored-flow-id": flowInfo.Flow.FlowId,
2000 "onu-id": onuID,
2001 "intf": Intf,
2002 })
2003 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302004 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002005 } else {
2006 gems := make([]uint32, 0)
2007 for _, gem := range flowInfo.Flow.PbitToGemport {
2008 gems = appendUnique32bit(gems, gem)
2009 }
2010 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2011 for _, gem := range gems {
2012 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
2013 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002014 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002015 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002016 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002017 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002018 "onu-id": onuID,
2019 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002020 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002021 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002022 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302023 }
2024 }
2025 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002026
2027 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2028 if isDatapathFlow(flow) {
2029 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2030 var inverseDirection string
2031 if flowDirection == Upstream {
2032 inverseDirection = Downstream
2033 } else {
2034 inverseDirection = Upstream
2035 }
2036
2037 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002038 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002040 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002041 }
2042 }
2043 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002044}
2045
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002046//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002047func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002048
Neha Sharma96b7bf22020-06-15 10:37:32 +00002049 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302050 var direction string
2051 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002052
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302053 for _, action := range flows.GetActions(flow) {
2054 if action.Type == flows.OUTPUT {
2055 if out := action.GetOutput(); out != nil {
2056 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002057 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302058 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002059 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002060 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002061 }
2062 }
2063 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002064
2065 if flows.HasGroup(flow) {
2066 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002067 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002068 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302069 direction = Upstream
2070 } else {
2071 direction = Downstream
2072 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302073
Girish Gowdracefae192020-03-19 18:14:10 -07002074 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002075 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002076
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002077 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002078}
2079
Esin Karamanae41e2b2019-12-17 18:13:13 +00002080//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2081func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2082 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2083 if ethType, ok := classifierInfo[EthType]; ok {
2084 if ethType.(uint32) == IPv4EthType {
2085 if ipProto, ok := classifierInfo[IPProto]; ok {
2086 if ipProto.(uint32) == IgmpProto {
2087 return true
2088 }
2089 }
2090 }
2091 }
2092 }
2093 return false
2094}
2095
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002096// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2097func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2098 // Step1 : Fill flowControlBlock
2099 // Step2 : Push the flowControlBlock to ONU channel
2100 // Step3 : Wait on response channel for response
2101 // Step4 : Return error value
2102 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2103 errChan := make(chan error)
2104 flowCb := flowControlBlock{
2105 ctx: ctx,
2106 addFlow: addFlow,
2107 flow: flow,
2108 flowMetadata: flowMetadata,
2109 errChan: &errChan,
2110 }
2111 inPort, outPort := getPorts(flow)
2112 var onuID uint32
2113 if inPort != InvalidPort && outPort != InvalidPort {
2114 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2115 }
2116 // inPort or outPort is InvalidPort for trap-from-nni flows.
2117 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2118 // Send the flowCb on the ONU flow channel
2119 f.incomingFlows[onuID] <- flowCb
2120 // Wait on the channel for flow handlers return value
2121 err := <-errChan
2122 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2123 return err
2124}
2125
2126// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2127// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2128func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2129 for {
2130 // block on the channel to receive an incoming flow
2131 // process the flow completely before proceeding to handle the next flow
2132 flowCb := <-subscriberFlowChannel
2133 if flowCb.addFlow {
2134 logger.Debugw(flowCb.ctx, "adding-flow",
2135 log.Fields{"device-id": f.deviceHandler.device.Id,
2136 "flowToAdd": flowCb.flow})
2137 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2138 // Pass the return value over the return channel
2139 *flowCb.errChan <- err
2140 } else {
2141 logger.Debugw(flowCb.ctx, "removing-flow",
2142 log.Fields{"device-id": f.deviceHandler.device.Id,
2143 "flowToRemove": flowCb.flow})
2144 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2145 // Pass the return value over the return channel
2146 *flowCb.errChan <- err
2147 }
2148 }
2149}
2150
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002151// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302152// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002153func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002154 classifierInfo := make(map[string]interface{})
2155 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002156 var UsMeterID uint32
2157 var DsMeterID uint32
2158
Neha Sharma96b7bf22020-06-15 10:37:32 +00002159 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302160 log.Fields{
2161 "flow": flow,
2162 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002163 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002164
Neha Sharma96b7bf22020-06-15 10:37:32 +00002165 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002166 if err != nil {
2167 // Error logging is already done in the called function
2168 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002169 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302170 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002171
Esin Karamanccb714b2019-11-29 15:02:06 +00002172 if flows.HasGroup(flow) {
2173 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002174 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002175 }
2176
manikkaraj k17652a72019-05-06 09:06:36 -04002177 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002178 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002179 if err != nil {
2180 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002181 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002182 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002183
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302185 log.Fields{
2186 "classifierinfo_inport": classifierInfo[InPort],
2187 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002188 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002189
Humera Kouser94d7a842019-08-25 19:04:32 -04002190 if ethType, ok := classifierInfo[EthType]; ok {
2191 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002192 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002193 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002194 }
2195 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002196 if ipProto, ok := classifierInfo[IPProto]; ok {
2197 if ipProto.(uint32) == IPProtoDhcp {
2198 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302199 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002201 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002202 }
2203 }
2204 }
2205 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002206 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002207 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002208 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002209 }
A R Karthick1f85b802019-10-11 05:06:05 +00002210
npujarec5762e2020-01-01 14:08:48 +05302211 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002212
Neha Sharma96b7bf22020-06-15 10:37:32 +00002213 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002214 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302215 return olterrors.NewErrNotFound("tpid-for-flow",
2216 log.Fields{
2217 "flow": flow,
2218 "intf-id": IntfID,
2219 "onu-id": onuID,
2220 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002221 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002222 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302223 log.Fields{
2224 "tp-id": TpID,
2225 "intf-id": intfID,
2226 "onu-id": onuID,
2227 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002228 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002229 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002230 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002231 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002232 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002233 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002234
2235 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002236 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002237}
Girish Gowdra3d633032019-12-10 16:37:05 +05302238
Esin Karamanccb714b2019-11-29 15:02:06 +00002239// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002240func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002241 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002242 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302243 "classifier-info": classifierInfo,
2244 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002245
Esin Karaman65409d82020-03-18 10:58:18 +00002246 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002247 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002248 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002249 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002250
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002251 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002252
David K. Bainbridge794735f2020-02-11 21:01:37 -08002253 onuID := NoneOnuID
2254 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002255
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002256 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002257 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002258 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002259 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002260 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2261 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002262 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002263 }
2264 groupID := actionInfo[GroupID].(uint32)
2265 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002266 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002267 FlowType: Multicast,
2268 NetworkIntfId: int32(networkInterfaceID),
2269 GroupId: groupID,
2270 Classifier: classifierProto,
2271 Priority: int32(flow.Priority),
2272 Cookie: flow.Cookie}
2273
Kent Hagermane6ff1012020-07-14 15:07:53 -04002274 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002275 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002276 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002277 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002278 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002279 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002280 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002281 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002282 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002283 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002284 //cached group can be removed now
2285 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2286 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2287 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002288 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002289
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002290 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2291 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2292 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002293 }
2294 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002295}
2296
Esin Karaman65409d82020-03-18 10:58:18 +00002297//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2298func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2299 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002301 if err != nil {
2302 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2303 }
2304 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002305 }
Esin Karaman65409d82020-03-18 10:58:18 +00002306 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302307 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002308 if e == nil && len(nniPorts) > 0 {
2309 return nniPorts[0], nil
2310 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302311 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002312}
2313
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002314//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002315func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002316
Neha Sharma96b7bf22020-06-15 10:37:32 +00002317 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302318 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002319 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302320 log.Fields{
2321 "intf-id": intfID,
2322 "onu-id": onuID,
2323 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002324 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302325 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002327
Neha Sharma96b7bf22020-06-15 10:37:32 +00002328 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002329 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002331 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002332 tpDownloadMsg,
2333 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
Thomas Lee S985938d2020-05-04 11:40:41 +05302334 f.deviceHandler.device.Type,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002335 onuDev.deviceType,
2336 onuDev.deviceID,
2337 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002338 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302339 return olterrors.NewErrCommunication("send-techprofile-download-request",
2340 log.Fields{
2341 "from-adapter": f.deviceHandler.device.Type,
2342 "to-adapter": onuDev.deviceType,
2343 "onu-id": onuDev.deviceID,
2344 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002345 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002346 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302347 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302348}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002349
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302350//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002351func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302352
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002353 f.onuGemInfoLock.Lock()
2354 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002355 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002356 // If the ONU already exists in onuGemInfo list, nothing to do
2357 for _, onu := range onugem {
2358 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2359 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2360 log.Fields{"onuID": onuID,
2361 "serialNum": serialNum})
2362 return nil
2363 }
2364 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002365
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302366 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002367 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002368 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002369 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302370 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302372 log.Fields{
2373 "intf-id": intfID,
2374 "onu-id": onuID,
2375 "serial-num": serialNum,
2376 "onu": onu,
2377 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002378 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002379}
2380
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302381//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302382func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002383
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002384 f.onuGemInfoLock.Lock()
2385 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002386
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302388 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002389 "gem-port-id": gemPort,
2390 "intf-id": intfID,
2391 "onu-id": onuID,
2392 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002393 "onu-gem": f.onuGemInfo})
2394 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302395 // update the gem to the local cache as well as to kv strore
2396 for idx, onu := range onugem {
2397 if onu.OnuID == onuID {
2398 // check if gem already exists , else update the cache and kvstore
2399 for _, gem := range onu.GemPorts {
2400 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302402 log.Fields{
2403 "gem": gemPort,
2404 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302405 return
2406 }
2407 }
2408 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002409 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002410 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302411 }
2412 }
npujarec5762e2020-01-01 14:08:48 +05302413 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302414 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002415 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302416 log.Fields{
2417 "intf-id": intfID,
2418 "onu-id": onuID,
2419 "gemPort": gemPort,
2420 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002421 return
2422 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002423 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302424 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002425 "gem-port-id": gemPort,
2426 "intf-id": intfID,
2427 "onu-id": onuID,
2428 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002429 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002430}
2431
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002432//getOnuIDfromGemPortMap Returns OnuID,nil if found or set 0,error if no onuId is found for serialNumber or (intfId, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002433func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302434
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002435 f.onuGemInfoLock.RLock()
2436 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302437
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002438 logger.Debugw(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302439 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002440 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002441 "onu-geminfo": f.onuGemInfo,
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002442 "intf-id": intfID,
2443 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302444 // get onuid from the onugem info cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002445 onugem := f.onuGemInfo
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002446
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302447 for _, onu := range onugem {
2448 for _, gem := range onu.GemPorts {
2449 if gem == gemPortID {
2450 return onu.OnuID, nil
2451 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002452 }
2453 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002454 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2455 "gem-port-id": gemPortID,
2456 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002457 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002458 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302459 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002460 "interface-id": intfID,
2461 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002462 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002463}
2464
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002465//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302466func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002467 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002468 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002469 var err error
2470
2471 if packetIn.IntfType == "pon" {
2472 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002473 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002474 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002475 return logicalPortNum, err
2476 }
2477 if packetIn.PortNo != 0 {
2478 logicalPortNum = packetIn.PortNo
2479 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002480 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002481 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002482 }
2483 // 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 +00002484 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002485 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002486 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002487 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002488 logger.Infow(ctx, "retrieved-logicalport-from-packet-in",
Shrey Baid26912972020-04-16 21:02:31 +05302489 log.Fields{
2490 "logical-port-num": logicalPortNum,
2491 "intf-type": packetIn.IntfType,
2492 "packet": hex.EncodeToString(packetIn.Pkt),
2493 })
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002494 return logicalPortNum, nil
2495}
2496
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002497//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002498func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002499 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002500
2501 ctag, priority, err := getCTagFromPacket(ctx, packet)
2502 if err != nil {
2503 return 0, err
2504 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302505
Esin Karaman7fb80c22020-07-16 14:23:33 +00002506 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002507 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002508 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002509 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002510 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302511 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002512 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302513 log.Fields{
2514 "pktinkey": pktInkey,
2515 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002516
2517 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002518 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302519 //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 +00002520 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302521 if err == nil {
2522 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002523 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302524 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002525 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302527 log.Fields{
2528 "pktinkey": pktInkey,
2529 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302530 return gemPortID, nil
2531 }
2532 }
Shrey Baid26912972020-04-16 21:02:31 +05302533 return uint32(0), olterrors.NewErrNotFound("gem-port",
2534 log.Fields{
2535 "pktinkey": pktInkey,
2536 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002537
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538}
2539
David K. Bainbridge794735f2020-02-11 21:01:37 -08002540func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002541 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002542 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002543 classifier[PacketTagType] = DoubleTag
2544 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 /* We manage flowId resource pool on per PON port basis.
2546 Since this situation is tricky, as a hack, we pass the NNI port
2547 index (network_intf_id) as PON port Index for the flowId resource
2548 pool. Also, there is no ONU Id available for trapping DHCP packets
2549 on NNI port, use onu_id as -1 (invalid)
2550 ****************** CAVEAT *******************
2551 This logic works if the NNI Port Id falls within the same valid
2552 range of PON Port Ids. If this doesn't work for some OLT Vendor
2553 we need to have a re-look at this.
2554 *********************************************
2555 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002556 onuID := -1
2557 uniID := -1
2558 gemPortID := -1
2559 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302561 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302562 return olterrors.NewErrNotFound("nni-intreface-id",
2563 log.Fields{
2564 "classifier": classifier,
2565 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002566 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302567 }
2568
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002569 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002570 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002571 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002572 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002573
David K. Bainbridge794735f2020-02-11 21:01:37 -08002574 classifierProto, err := makeOpenOltClassifierField(classifier)
2575 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002576 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002578 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002579 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002580 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002581 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002582 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002583 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002584 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2585 OnuId: int32(onuID), // OnuId not required
2586 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002587 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002588 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002589 AllocId: int32(allocID), // AllocId not used
2590 NetworkIntfId: int32(networkInterfaceID),
2591 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002592 Classifier: classifierProto,
2593 Action: actionProto,
2594 Priority: int32(logicalFlow.Priority),
2595 Cookie: logicalFlow.Cookie,
2596 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002597 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002598 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002599 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002600 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002601 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2602 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2603 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002604 }
2605 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002606}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002607
Esin Karamanae41e2b2019-12-17 18:13:13 +00002608//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2609func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2610 var packetType string
2611 ovid, ivid := false, false
2612 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2613 vid := vlanID & VlanvIDMask
2614 if vid != ReservedVlan {
2615 ovid = true
2616 }
2617 }
2618 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2619 vid := uint32(metadata)
2620 if vid != ReservedVlan {
2621 ivid = true
2622 }
2623 }
2624 if ovid && ivid {
2625 packetType = DoubleTag
2626 } else if !ovid && !ivid {
2627 packetType = Untagged
2628 } else {
2629 packetType = SingleTag
2630 }
2631 return packetType
2632}
2633
2634//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002635func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002636 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002637 action := make(map[string]interface{})
2638 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2639 action[TrapToHost] = true
2640 /* We manage flowId resource pool on per PON port basis.
2641 Since this situation is tricky, as a hack, we pass the NNI port
2642 index (network_intf_id) as PON port Index for the flowId resource
2643 pool. Also, there is no ONU Id available for trapping packets
2644 on NNI port, use onu_id as -1 (invalid)
2645 ****************** CAVEAT *******************
2646 This logic works if the NNI Port Id falls within the same valid
2647 range of PON Port Ids. If this doesn't work for some OLT Vendor
2648 we need to have a re-look at this.
2649 *********************************************
2650 */
2651 onuID := -1
2652 uniID := -1
2653 gemPortID := -1
2654 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002655 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002656 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302657 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002658 "classifier": classifier,
2659 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002660 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002661 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002662 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002663 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002664 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002665 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002666
David K. Bainbridge794735f2020-02-11 21:01:37 -08002667 classifierProto, err := makeOpenOltClassifierField(classifier)
2668 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002669 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002672 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002673 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002674 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002675 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002676 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002677 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2678 OnuId: int32(onuID), // OnuId not required
2679 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002681 FlowType: Downstream,
2682 AllocId: int32(allocID), // AllocId not used
2683 NetworkIntfId: int32(networkInterfaceID),
2684 GemportId: int32(gemPortID), // GemportId not used
2685 Classifier: classifierProto,
2686 Action: actionProto,
2687 Priority: int32(logicalFlow.Priority),
2688 Cookie: logicalFlow.Cookie,
2689 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002690 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002691 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002692 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002693 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002694 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2695 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2696 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002697 }
2698 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002699}
2700
salmansiddiqui7ac62132019-08-22 03:58:50 +00002701func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2702 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302703 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002704 }
2705 if Dir == tp_pb.Direction_UPSTREAM {
2706 return "upstream", nil
2707 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2708 return "downstream", nil
2709 }
2710 return "", nil
2711}
2712
Kent Hagermane6ff1012020-07-14 15:07:53 -04002713// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302714func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002715 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002716 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002717 var gemPort uint32
2718 intfID := args[IntfID]
2719 onuID := args[OnuID]
2720 uniID := args[UniID]
2721 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002722 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002723 pbitToGem := make(map[uint32]uint32)
2724
2725 if len(gemPorts) == 1 {
2726 // If there is only single gemport use that and do not populate pbitToGem map
2727 gemPort = gemPorts[0]
2728 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2729 for idx, gemID := range gemPorts {
2730 switch TpInst := TpInst.(type) {
2731 case *tp.TechProfile:
2732 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2733 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2734 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2735 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2736 // this pcp bit traffic.
2737 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2738 if pbitSet == pbit1 {
2739 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2740 pbitToGem[pcp] = gemID
2741 }
2742 }
2743 default:
2744 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2745 return
2746 }
2747 }
2748 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2749 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2750 tp_pb.Direction_UPSTREAM,
2751 pcp.(uint32))
2752 }
2753
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754 if ipProto, ok := classifierInfo[IPProto]; ok {
2755 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002756 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002757 "tp-id": tpID,
2758 "alloc-id": allocID,
2759 "intf-id": intfID,
2760 "onu-id": onuID,
2761 "uni-id": uniID,
2762 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002763 //Adding DHCP upstream flow
2764 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2765 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002766 }
2767
Girish Gowdra32625212020-04-29 11:26:35 -07002768 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002769 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302770 log.Fields{
2771 "intf-id": intfID,
2772 "onu-id": onuID,
2773 "uni-id": uniID,
2774 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002775 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2776 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002777 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002778 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002780 return
2781 }
2782 } else if ethType, ok := classifierInfo[EthType]; ok {
2783 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002784 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002785 "intf-id": intfID,
2786 "onu-id": onuID,
2787 "uni-id": uniID,
2788 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002789 var vlanID uint32
2790 if val, ok := classifierInfo[VlanVid]; ok {
2791 vlanID = (val.(uint32)) & VlanvIDMask
2792 } else {
2793 vlanID = DefaultMgmtVlan
2794 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002795 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2796 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002797 }
2798 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002799 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002801 "intf-id": intfID,
2802 "onu-id": onuID,
2803 "uni-id": uniID,
2804 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002805 //Adding HSIA upstream flow
2806 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2807 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002808 }
2809 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002810 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002811 "intf-id": intfID,
2812 "onu-id": onuID,
2813 "uni-id": uniID,
2814 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002815 //Adding HSIA downstream flow
2816 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2817 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002818 }
2819 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002820 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302821 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002822 "intf-id": intfID,
2823 "onu-id": onuID,
2824 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302825 "classifier": classifierInfo,
2826 "action": actionInfo,
2827 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002828 return
2829 }
2830 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002831 go func() {
2832 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2833 logger.Warn(ctx, err)
2834 }
2835 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002836}
2837
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2839 f.flowsUsedByGemPortKey.RLock()
2840 flowIDList := f.flowsUsedByGemPort[gemPortID]
2841 f.flowsUsedByGemPortKey.RUnlock()
2842 return len(flowIDList) > 1
2843
Gamze Abakafee36392019-10-03 11:17:24 +00002844}
2845
npujarec5762e2020-01-01 14:08:48 +05302846func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2847 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002848 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2849 for _, currentGemPort := range currentGemPorts {
2850 for _, tpGemPort := range tpGemPorts {
2851 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2852 return true, currentGemPort
2853 }
2854 }
2855 }
Girish Gowdra54934262019-11-13 14:19:55 +05302856 if tpInst.InstanceCtrl.Onu == "single-instance" {
2857 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002858 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002859 logger.Warn(ctx, err)
2860 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002861 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002862 logger.Warn(ctx, err)
2863 }
Girish Gowdra54934262019-11-13 14:19:55 +05302864
2865 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2866 // still be used on other uni ports.
2867 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2868 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002869 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002870 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302871 for i := 0; i < len(tpInstances); i++ {
2872 tpI := tpInstances[i]
2873 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302874 for _, tpGemPort := range tpGemPorts {
2875 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002876 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302877 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302878 }
2879 }
2880 }
2881 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002882 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002883 return false, 0
2884}
2885
Neha Sharma96b7bf22020-06-15 10:37:32 +00002886func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002887 for _, field := range flows.GetOfbFields(flow) {
2888 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002891 } else if field.Type == flows.ETH_DST {
2892 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002893 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002894 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002897 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002899 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002900 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302901 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002902 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002903 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002904 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002905 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002906 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002908 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002909 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002910 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002911 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002912 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002913 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002914 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002915 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002916 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002917 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002918 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002919 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002920 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002921 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002922 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002923 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002925 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 return
2927 }
2928 }
2929}
2930
Neha Sharma96b7bf22020-06-15 10:37:32 +00002931func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002932 for _, action := range flows.GetActions(flow) {
2933 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002934 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002935 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002936 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002937 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002938 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002939 }
Scott Baker355d1742019-10-24 10:57:52 -07002940 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002942 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002943 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002944 if out := action.GetPush(); out != nil {
2945 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002946 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002947 } else {
2948 actionInfo[PushVlan] = true
2949 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302951 log.Fields{
2952 "push-tpid": actionInfo[TPID].(uint32),
2953 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002954 }
2955 }
Scott Baker355d1742019-10-24 10:57:52 -07002956 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002957 if out := action.GetSetField(); out != nil {
2958 if field := out.GetField(); field != nil {
2959 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002960 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2963 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 }
2965 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002966 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002968 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002969 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002970 }
2971 }
2972 return nil
2973}
2974
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002976 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002977 fieldtype := ofbField.GetType()
2978 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002979 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2980 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002981 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002982 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002983 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002984 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002985 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2986 pcp := ofbField.GetVlanPcp()
2987 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002988 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002989 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002990 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002991 }
2992 }
2993}
2994
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002996 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002997 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002998 } else {
2999 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003000 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003001 }
3002}
3003
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003005 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003006 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003007 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3008 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003009 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003010 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303012 log.Fields{
3013 "newinport": classifierInfo[InPort].(uint32),
3014 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303016 return olterrors.NewErrNotFound("child-in-port",
3017 log.Fields{
3018 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3019 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003020 }
3021 }
3022 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003023 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003025 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003026 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003027 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303029 log.Fields{
3030 "newoutport": actionInfo[Output].(uint32),
3031 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303033 return olterrors.NewErrNotFound("out-port",
3034 log.Fields{
3035 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3036 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 }
3038 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3039 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003040 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303043 log.Fields{
3044 "newinport": actionInfo[Output].(uint32),
3045 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303047 return olterrors.NewErrNotFound("nni-port",
3048 log.Fields{
3049 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3050 "in-port": classifierInfo[InPort].(uint32),
3051 "out-port": actionInfo[Output].(uint32),
3052 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 }
3054 }
3055 }
3056 return nil
3057}
Gamze Abakafee36392019-10-03 11:17:24 +00003058
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003060 /* Metadata 8 bytes:
3061 Most Significant 2 Bytes = Inner VLAN
3062 Next 2 Bytes = Tech Profile ID(TPID)
3063 Least Significant 4 Bytes = Port ID
3064 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3065 subscriber related flows.
3066 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003068 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003069 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003070 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003072 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003073}
3074
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003075func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3076 for _, sliceElement := range slice {
3077 if sliceElement == item {
3078 return slice
3079 }
3080 }
3081 return append(slice, item)
3082}
3083
3084func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003085 for _, sliceElement := range slice {
3086 if sliceElement == item {
3087 return slice
3088 }
3089 }
3090 return append(slice, item)
3091}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303092
3093// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303095
3096 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3097 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003099 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003101 log.Fields{
3102 "port-number": action[Output].(uint32),
3103 "error": err})
3104 return uint32(0), err
3105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303107 return intfID, nil
3108 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003110 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003112 log.Fields{
3113 "port-number": action[Output].(uint32),
3114 "error": err})
3115 return uint32(0), err
3116 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303118 return intfID, nil
3119 }
3120 return uint32(0), nil
3121}
3122
3123// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003124func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3125 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3126 if err != nil {
3127 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3128 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3129 return
3130 }
3131 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003132
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003133 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003134 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003135 f.packetInGemPortLock.RUnlock()
3136
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303137 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003138 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139 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 +05303140 log.Fields{
3141 "pktinkey": pktInkey,
3142 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003143 return
3144 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303145 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003146 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003147 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003148 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003149
npujarec5762e2020-01-01 14:08:48 +05303150 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 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 +05303152 log.Fields{
3153 "pktinkey": pktInkey,
3154 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303155}
3156
Esin Karaman7fb80c22020-07-16 14:23:33 +00003157//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3158func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3159 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003160 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003161 return 0, 0, errors.New("invalid packet length")
3162 }
3163 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3164 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3165
3166 var index int8
3167 if outerEthType == 0x8100 {
3168 if innerEthType == 0x8100 {
3169 // q-in-q 802.1ad or 802.1q double tagged packet.
3170 // get the inner vlanId
3171 index = 18
3172 } else {
3173 index = 14
3174 }
3175 priority := (packet[index] >> 5) & 0x7
3176 //13 bits composes vlanId value
3177 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3178 return vlan, priority, nil
3179 }
3180 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3181 return 0, 0, nil
3182}
3183
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303184// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303185func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003186
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003187 f.onuGemInfoLock.Lock()
3188 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003189
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003190 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303191 for idx, onu := range onugem {
3192 if onu.OnuID == onuID {
3193 for _, uni := range onu.UniPorts {
3194 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003195 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 +05303196 return
3197 }
3198 }
3199 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003200 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303201 }
3202 }
npujarec5762e2020-01-01 14:08:48 +05303203 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003204
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303205}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303206
npujarec5762e2020-01-01 14:08:48 +05303207func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3208 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303209 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303211 return
3212 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303214 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003215 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303216 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303218}
Esin Karamanccb714b2019-11-29 15:02:06 +00003219
Girish Gowdra9602eb42020-09-09 15:50:39 -07003220//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3221// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003222func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003223 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003224 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003225 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3226 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3227
Esin Karamanccb714b2019-11-29 15:02:06 +00003228 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003229 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 -07003230 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003231 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003232
3233 var onuID = int32(NoneOnuID)
3234 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003235 var flowID uint64
3236 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3237 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3238 log.Fields{
3239 "flow": flow,
3240 "device-id": f.deviceHandler.device.Id,
3241 "intf-id": networkInterfaceID,
3242 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003243 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003244 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3245 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3246 log.Fields{
3247 "flow": flowInfo.Flow,
3248 "flow-id": flow.Id,
3249 "device-id": f.deviceHandler.device.Id})
3250 // Remove from device
3251 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3252 // DKB
3253 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3254 log.Fields{
3255 "flow-id": flow.Id,
3256 "error": err})
3257 return err
3258 }
3259 // Remove flow from KV store
3260 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00003261}
3262
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003263// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3264func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3265 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3266 if err != nil {
3267 _ = olterrors.NewErrNotFound("onu", log.Fields{
3268 "pon-port": f.ponPortIdx}, err).Log()
3269 return
3270 }
3271
3272 f.subscriberDataPathFlowIDMapLock.Lock()
3273 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3274
3275 for _, onu := range onuGemInfo {
3276 for _, uniID := range onu.UniPorts {
3277 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3278 if err != nil {
3279 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3280 }
3281 for _, flowID := range flowIDs {
3282 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3283 if flowInfo == nil {
3284 // Error is already logged in the called function
3285 continue
3286 }
3287 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3288 flowInfo.Flow.FlowType == Downstream &&
3289 flowInfo.Flow.Classifier.OVid > 0 &&
3290 flowInfo.Flow.TechProfileId > 0 {
3291 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3292 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3293 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3294 }
3295 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3296 flowInfo.Flow.FlowType == Upstream &&
3297 flowInfo.Flow.Action.OVid > 0 &&
3298 flowInfo.Flow.TechProfileId > 0 {
3299 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3300 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3301 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3302 }
3303 }
3304 }
3305 }
3306 }
3307}
3308
3309// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3310func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3311 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3312}