blob: 44c67880f95e2227a78119a2434f1fda0abd5565 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
serkant.uluderya4aff1862020-09-17 23:35:26 +030025 "strings"
26 "sync"
27
Girish Gowdraa09aeab2020-09-14 16:30:52 -070028 "github.com/opencord/voltha-lib-go/v4/pkg/flows"
29 "github.com/opencord/voltha-lib-go/v4/pkg/log"
30 tp "github.com/opencord/voltha-lib-go/v4/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080031 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
Girish Gowdraa09aeab2020-09-14 16:30:52 -070032 "github.com/opencord/voltha-protos/v4/go/common"
33 ic "github.com/opencord/voltha-protos/v4/go/inter_container"
34 ofp "github.com/opencord/voltha-protos/v4/go/openflow_13"
35 openoltpb2 "github.com/opencord/voltha-protos/v4/go/openolt"
36 tp_pb "github.com/opencord/voltha-protos/v4/go/tech_profile"
37 "github.com/opencord/voltha-protos/v4/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040038
Thomas Lee S94109f12020-03-03 16:39:29 +053039 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000040 "google.golang.org/grpc/codes"
41 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053042)
43
44const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070045 //IPProtoDhcp flow category
46 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053047
Girish Gowdraa09aeab2020-09-14 16:30:52 -070048 //IgmpProto proto value
49 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050
51 //EapEthType eapethtype value
52 EapEthType = 0x888e
53 //LldpEthType lldp ethtype value
54 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000055 //IPv4EthType IPv4 ethernet type value
56 IPv4EthType = 0x800
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057
Andrea Campanella7acc0b92020-02-14 09:20:49 +010058 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
59 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040060
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070061 //DefaultMgmtVlan default vlan value
62 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053063
manikkaraj kbf256be2019-03-25 00:13:48 +053064 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070065
David K. Bainbridge82efc492019-09-04 09:57:11 -070066 //Upstream constant
67 Upstream = "upstream"
68 //Downstream constant
69 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000070 //Multicast constant
71 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072 //PacketTagType constant
73 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 //Untagged constant
75 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070076 //SingleTag constant
77 SingleTag = "single_tag"
78 //DoubleTag constant
79 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053080
81 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070082
83 //EthType constant
84 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000085 //EthDst constant
86 EthDst = "eth_dst"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070087 //TPID constant
88 TPID = "tpid"
89 //IPProto constant
90 IPProto = "ip_proto"
91 //InPort constant
92 InPort = "in_port"
93 //VlanVid constant
94 VlanVid = "vlan_vid"
95 //VlanPcp constant
96 VlanPcp = "vlan_pcp"
97
98 //UDPDst constant
99 UDPDst = "udp_dst"
100 //UDPSrc constant
101 UDPSrc = "udp_src"
102 //Ipv4Dst constant
103 Ipv4Dst = "ipv4_dst"
104 //Ipv4Src constant
105 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700106 //Metadata constant
107 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 //TunnelID constant
109 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700110 //Output constant
111 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000112 //GroupID constant
113 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 // Actions
115
116 //PopVlan constant
117 PopVlan = "pop_vlan"
118 //PushVlan constant
119 PushVlan = "push_vlan"
120 //TrapToHost constant
121 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400122 //MaxMeterBand constant
123 MaxMeterBand = 2
124 //VlanPCPMask contant
125 VlanPCPMask = 0xFF
126 //VlanvIDMask constant
127 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000128 //IntfID constant
129 IntfID = "intfId"
130 //OnuID constant
131 OnuID = "onuId"
132 //UniID constant
133 UniID = "uniId"
134 //PortNo constant
135 PortNo = "portNo"
136 //AllocID constant
137 AllocID = "allocId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000138
139 //NoneOnuID constant
140 NoneOnuID = -1
141 //NoneUniID constant
142 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700143
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700144 // Max number of flows that can be queued per ONU
145 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530146
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700147 bitMapPrefix = "0b"
148 pbit1 = '1'
149)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400150
Gamze Abakafee36392019-10-03 11:17:24 +0000151type schedQueue struct {
152 direction tp_pb.Direction
153 intfID uint32
154 onuID uint32
155 uniID uint32
156 tpID uint32
157 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700158 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000159 meterID uint32
160 flowMetadata *voltha.FlowMetadata
161}
162
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700163// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
164type subscriberDataPathFlowIDKey struct {
165 intfID uint32
166 onuID uint32
167 uniID uint32
168 direction string
169 tpID uint32
170}
171
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700172// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
173// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
174// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
175// flow and processes it serially
176type flowControlBlock struct {
177 ctx context.Context // Flow handler context
178 addFlow bool // if true flow to be added, else removed
179 flow *voltha.OfpFlowStats // Flow message
180 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
181 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000182}
183
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700184//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530185type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700186 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
187 techprofile map[uint32]tp.TechProfileIf
188 deviceHandler *DeviceHandler
189 grpMgr *OpenOltGroupMgr
190 resourceMgr *rsrcMgr.OpenOltResourceMgr
191
192 onuIdsLock sync.RWMutex // TODO: Do we need this?
193
194 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
195 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
196
197 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
198 packetInGemPortLock sync.RWMutex
199
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700200 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700202 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700203 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700204
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700205 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
206 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
207 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
208 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700209
210 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
211 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
212 incomingFlows []chan flowControlBlock
manikkaraj kbf256be2019-03-25 00:13:48 +0530213}
214
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700215//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700216func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000217 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530218 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530219 var err error
220 var idx uint32
221
manikkaraj kbf256be2019-03-25 00:13:48 +0530222 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700223 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530224 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000225 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000226 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
227 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530228 return nil
229 }
William Kurkian740a09c2019-10-23 17:07:38 -0400230 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700231 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700233 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700234 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700235 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
236 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700237
238 // Create a slice of buffered channels for handling concurrent flows per ONU.
239 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
240 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
241 for i := range flowMgr.incomingFlows {
242 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
243 // Spin up a go routine to handling incoming flows (add/remove).
244 // There will be on go routine per ONU.
245 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
246 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
247 }
248
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530249 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700250 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
251 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530252 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700253 //Load flowID list per gem map per interface from the kvstore.
254 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000255 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700256 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700257 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000258 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530259 return &flowMgr
260}
261
Kent Hagermane6ff1012020-07-14 15:07:53 -0400262func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700263 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
264 // Flow is not replicated in this case, we need to register the flow for a single gem-port
265 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
266 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
267 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
268 for _, gemPort := range deviceFlow.PbitToGemport {
269 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
270 return err
271 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700272 }
Gamze Abakafee36392019-10-03 11:17:24 +0000273 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274 return nil
275}
276
277func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
278 f.flowsUsedByGemPortKey.Lock()
279 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
280 if !ok {
281 flowIDList = []uint64{flowFromCore.Id}
282 }
283 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
284 f.flowsUsedByGemPort[gemPortID] = flowIDList
285 f.flowsUsedByGemPortKey.Unlock()
286
287 // update the flowids for a gem to the KVstore
288 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400289}
290
Girish Gowdra9602eb42020-09-09 15:50:39 -0700291func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000292 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200293 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000294 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530295 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700296 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530297
Neha Sharma96b7bf22020-06-15 10:37:32 +0000298 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530299 "device-id": f.deviceHandler.device.Id,
300 "intf-id": intfID,
301 "onu-id": onuID,
302 "uni-id": uniID,
303 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700304 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530305 "action": actionInfo,
306 "usmeter-iD": UsMeterID,
307 "dsmeter-iD": DsMeterID,
308 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400309 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
310 // is because the flow is an NNI flow and there would be no onu resources associated with it
311 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400312 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200313 cause := "no-onu-id-for-flow"
314 fields := log.Fields{
315 "onu": onuID,
316 "port-no": portNo,
317 "classifer": classifierInfo,
318 "action": actionInfo,
319 "device-id": f.deviceHandler.device.Id}
320 logger.Errorw(ctx, cause, fields)
321 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530322 }
323
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700324 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000325 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530326 "uni": uni,
327 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530328
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700329 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
330 "device-id": f.deviceHandler.device.Id,
331 "intf-id": intfID,
332 "onu-id": onuID,
333 "uni-id": uniID,
334 "port-no": portNo,
335 "classifier": classifierInfo,
336 "action": actionInfo,
337 "usmeter-id": UsMeterID,
338 "dsmeter-id": DsMeterID,
339 "tp-id": TpID})
340 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
341 if allocID == 0 || gemPorts == nil || TpInst == nil {
342 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
343 return olterrors.NewErrNotFound(
344 "alloc-id-gem-ports-tp-unavailable",
345 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400346 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700347 args := make(map[string]uint32)
348 args[IntfID] = intfID
349 args[OnuID] = onuID
350 args[UniID] = uniID
351 args[PortNo] = portNo
352 args[AllocID] = allocID
353
354 /* Flows can be added specific to gemport if p-bits are received.
355 * If no pbit mentioned then adding flows for all gemports
356 */
357 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
358
Andrea Campanellabfe08432020-09-11 17:07:03 +0200359 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530360}
361
salmansiddiqui7ac62132019-08-22 03:58:50 +0000362// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530363func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400364
Neha Sharma96b7bf22020-06-15 10:37:32 +0000365 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530366 log.Fields{"dir": sq.direction,
367 "intf-id": sq.intfID,
368 "onu-id": sq.onuID,
369 "uni-id": sq.uniID,
370 "tp-id": sq.tpID,
371 "meter-id": sq.meterID,
372 "tp-inst": sq.tpInst,
373 "flowmetadata": sq.flowMetadata,
374 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400375
Gamze Abakafee36392019-10-03 11:17:24 +0000376 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000377 if err != nil {
378 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400379 }
380
381 /* Lets make a simple assumption that if the meter-id is present on the KV store,
382 * then the scheduler and queues configuration is applied on the OLT device
383 * in the given direction.
384 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000385
Manikkaraj kb1d51442019-07-23 10:41:02 -0400386 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530387 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400388 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530389 return olterrors.NewErrNotFound("meter",
390 log.Fields{"intf-id": sq.intfID,
391 "onu-id": sq.onuID,
392 "uni-id": sq.uniID,
393 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000395
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000397 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000398 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400399 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530401 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800402 "unsupported": "meter-id",
403 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530404 "meter-id-in-flow": sq.meterID,
405 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000407
Neha Sharma96b7bf22020-06-15 10:37:32 +0000408 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530409 log.Fields{
410 "meter-id": sq.meterID,
411 "direction": Direction,
412 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000413
Gamze Abakafee36392019-10-03 11:17:24 +0000414 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000415 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000416 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000417 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400418 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000419
420 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530421 return olterrors.NewErrNotFound("scheduler-config",
422 log.Fields{
423 "intf-id": sq.intfID,
424 "direction": sq.direction,
425 "tp-inst": sq.tpInst,
426 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000427 }
428
Manikkaraj kb1d51442019-07-23 10:41:02 -0400429 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000430 if sq.flowMetadata != nil {
431 for _, meter := range sq.flowMetadata.Meters {
432 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400433 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000434 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530435 log.Fields{"meterConfig": meterConfig,
436 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400437 break
438 }
439 }
440 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000441 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400442 }
443 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530444 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800445 "reason": "Could-not-get-meterbands-from-flowMetadata",
446 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530447 "meter-id": sq.meterID,
448 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400449 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000450 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530451 log.Fields{"Bands": meterConfig.Bands,
452 "meter-id": sq.meterID,
453 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530454 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800455 "reason": "Invalid-number-of-bands-in-meter",
456 "meterband-count": len(meterConfig.Bands),
457 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530458 "meter-id": sq.meterID,
459 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400460 }
461 cir := meterConfig.Bands[0].Rate
462 cbs := meterConfig.Bands[0].BurstSize
463 eir := meterConfig.Bands[1].Rate
464 ebs := meterConfig.Bands[1].BurstSize
465 pir := cir + eir
466 pbs := cbs + ebs
467 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
468
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700469 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000470 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700472 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530473 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
474 log.Fields{"intf-id": sq.intfID,
475 "direction": sq.direction,
476 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400477 }
478
salmansiddiqui7ac62132019-08-22 03:58:50 +0000479 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 * store the meter id on the KV store, for further reference.
481 */
npujarec5762e2020-01-01 14:08:48 +0530482 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 +0530483 return olterrors.NewErrAdapter("failed-updating-meter-id",
484 log.Fields{"onu-id": sq.onuID,
485 "meter-id": sq.meterID,
486 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000488 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530489 log.Fields{"direction": Direction,
490 "Meter": meterConfig,
491 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 return nil
493}
494
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700495func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000496 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000497
498 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530499 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000503 }
504
Neha Sharma96b7bf22020-06-15 10:37:32 +0000505 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530506 log.Fields{
507 "direction": sq.direction,
508 "TrafficScheds": TrafficSched,
509 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530510 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000511 IntfId: sq.intfID, OnuId: sq.onuID,
512 UniId: sq.uniID, PortNo: sq.uniPort,
513 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000514 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000515 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000516 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530517 "direction": sq.direction,
518 "traffic-queues": trafficQueues,
519 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000520
521 // On receiving the CreateTrafficQueues request, the driver should create corresponding
522 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000523 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530524 log.Fields{"direction": sq.direction,
525 "traffic-queues": trafficQueues,
526 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530527 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000528 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
529 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000530 TrafficQueues: trafficQueues,
531 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530532 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000533 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000534 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530535 "direction": sq.direction,
536 "traffic-queues": trafficQueues,
537 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000538
Esin Karamanccb714b2019-11-29 15:02:06 +0000539 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000540 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000541 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700542 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000543 //assumed that there is only one queue per PON for the multicast service
544 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
545 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000546 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000547 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700548 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000549 gemPortID: multicastQueuePerPonPort.GemportId,
550 servicePriority: multicastQueuePerPonPort.Priority,
551 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700552 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000553 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400554 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
555 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
556 return err
557 }
Shrey Baid26912972020-04-16 21:02:31 +0530558
Neha Sharma96b7bf22020-06-15 10:37:32 +0000559 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000560 }
561 }
562 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000563 return nil
564}
565
salmansiddiqui7ac62132019-08-22 03:58:50 +0000566// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530567func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400568
569 var Direction string
570 var SchedCfg *tp_pb.SchedulerConfig
571 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530573 log.Fields{
574 "direction": sq.direction,
575 "intf-id": sq.intfID,
576 "onu-id": sq.onuID,
577 "uni-id": sq.uniID,
578 "uni-port": sq.uniPort,
579 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000580 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000581 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400582 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000583 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400585 Direction = "downstream"
586 }
587
Girish Kumar8f73fe02019-12-09 13:19:37 +0000588 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530589 return olterrors.NewErrNotFound("scheduler-config",
590 log.Fields{
591 "int-id": sq.intfID,
592 "direction": sq.direction,
593 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 }
595
npujarec5762e2020-01-01 14:08:48 +0530596 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400597 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530598 return olterrors.NewErrNotFound("meter",
599 log.Fields{
600 "onu-id": sq.onuID,
601 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400602 }
603 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000604 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530605 log.Fields{
606 "direction": Direction,
607 "intf-id": sq.intfID,
608 "onu-id": sq.onuID,
609 "uni-id": sq.uniID,
610 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611 return nil
612 }
613 cir := KVStoreMeter.Bands[0].Rate
614 cbs := KVStoreMeter.Bands[0].BurstSize
615 eir := KVStoreMeter.Bands[1].Rate
616 ebs := KVStoreMeter.Bands[1].BurstSize
617 pir := cir + eir
618 pbs := cbs + ebs
619
620 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
621
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700622 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000623 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000624
Neha Sharma96b7bf22020-06-15 10:37:32 +0000625 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530627 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
628 log.Fields{
629 "intf-id": sq.intfID,
630 "direction": sq.direction,
631 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000632 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400633
npujarec5762e2020-01-01 14:08:48 +0530634 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000635 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
636 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000637 TrafficQueues: TrafficQueues,
638 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000639 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530640 log.Fields{
641 "intf-id": sq.intfID,
642 "traffic-queues": TrafficQueues,
643 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000645 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530646 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000647 IntfId: sq.intfID, OnuId: sq.onuID,
648 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400649 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000650 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530651 log.Fields{
652 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700653 "traffic-schedulers": TrafficSched,
654 "onu-id": sq.onuID,
655 "uni-id": sq.uniID,
656 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400657 }
658
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700659 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
660 log.Fields{"device-id": f.deviceHandler.device.Id,
661 "intf-id": sq.intfID,
662 "onu-id": sq.onuID,
663 "uni-id": sq.uniID,
664 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000665
666 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400667 * delete the meter id on the KV store.
668 */
npujarec5762e2020-01-01 14:08:48 +0530669 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530671 return olterrors.NewErrAdapter("unable-to-remove-meter",
672 log.Fields{
673 "onu": sq.onuID,
674 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700675 "device-id": f.deviceHandler.device.Id,
676 "intf-id": sq.intfID,
677 "onu-id": sq.onuID,
678 "uni-id": sq.uniID,
679 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000681 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530682 log.Fields{
683 "meter-id": KVStoreMeter.MeterId,
684 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700685 "device-id": f.deviceHandler.device.Id,
686 "intf-id": sq.intfID,
687 "onu-id": sq.onuID,
688 "uni-id": sq.uniID,
689 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400690 return err
691}
692
Gamze Abakafee36392019-10-03 11:17:24 +0000693// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700694func (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 +0000695 var allocIDs []uint32
696 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530697 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530698 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000699 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000700
npujarec5762e2020-01-01 14:08:48 +0530701 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
702 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000703 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530704
Neha Sharma96b7bf22020-06-15 10:37:32 +0000705 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530706 "intf-id": intfID,
707 "onu-id": onuID,
708 "uni-id": uniID,
709 "device-id": f.deviceHandler.device.Id,
710 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530711
Manikkaraj kb1d51442019-07-23 10:41:02 -0400712 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530713 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000714 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000715 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530716 log.Fields{
717 "path": tpPath,
718 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530719 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000720 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530721 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000722 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530723 log.Fields{
724 "error": err,
725 "tp-id": TpID,
726 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000727 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530728 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400729 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
730 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
731 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530732 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000733 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530734 log.Fields{
735 "uni": uni,
736 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530737 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530738 }
Gamze Abakafee36392019-10-03 11:17:24 +0000739
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700740 switch tpInst := techProfileInstance.(type) {
741 case *tp.TechProfile:
742 if UsMeterID != 0 {
743 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
744 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
745 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000746 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700747 log.Fields{
748 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700749 "onu-id": onuID,
750 "uni-id": uniID,
751 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700752 "meter-id": UsMeterID,
753 "device-id": f.deviceHandler.device.Id})
754 return 0, nil, nil
755 }
756 }
757 if DsMeterID != 0 {
758 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
759 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
760 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000761 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700762 log.Fields{
763 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700764 "onu-id": onuID,
765 "uni-id": uniID,
766 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700767 "meter-id": DsMeterID,
768 "device-id": f.deviceHandler.device.Id})
769 return 0, nil, nil
770 }
771 }
772 allocID := tpInst.UsScheduler.AllocID
773 for _, gem := range tpInst.UpstreamGemPortAttributeList {
774 gemPortIDs = append(gemPortIDs, gem.GemportID)
775 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700776 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000777
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700778 if tpInstanceExists {
779 return allocID, gemPortIDs, techProfileInstance
780 }
781
782 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700783 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000785 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700786 log.Fields{
787 "alloc-ids": allocIDs,
788 "gemports": allgemPortIDs,
789 "device-id": f.deviceHandler.device.Id})
790 // Send Tconts and GEM ports to KV store
791 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530792 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700793 case *tp.EponProfile:
794 // CreateSchedulerQueues for EPON needs to be implemented here
795 // when voltha-protos for EPON is completed.
796 allocID := tpInst.AllocID
797 for _, gem := range tpInst.UpstreamQueueAttributeList {
798 gemPortIDs = append(gemPortIDs, gem.GemportID)
799 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700800 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700801
802 if tpInstanceExists {
803 return allocID, gemPortIDs, techProfileInstance
804 }
805
806 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700807 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700808 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700810 log.Fields{
811 "alloc-ids": allocIDs,
812 "gemports": allgemPortIDs,
813 "device-id": f.deviceHandler.device.Id})
814 // Send Tconts and GEM ports to KV store
815 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
816 return allocID, gemPortIDs, techProfileInstance
817 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700819 log.Fields{
820 "tpInst": tpInst})
821 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530822 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530823}
824
npujarec5762e2020-01-01 14:08:48 +0530825func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530826
Neha Sharma96b7bf22020-06-15 10:37:32 +0000827 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530828 log.Fields{
829 "intf-id": intfID,
830 "onu-id": onuID,
831 "uni-id": uniID,
832 "alloc-id": allocID,
833 "gemport-ids": gemPortIDs,
834 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530836 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000837 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 +0530838 }
npujarec5762e2020-01-01 14:08:48 +0530839 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 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 +0530841 }
npujarec5762e2020-01-01 14:08:48 +0530842 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000843 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 +0530844 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000845 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 -0400846 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530847 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400848 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530849}
850
Neha Sharma96b7bf22020-06-15 10:37:32 +0000851func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000852 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530853 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000854 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700855 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400856 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000857 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530858 log.Fields{
859 "intf-id": intfID,
860 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530861 }
862 }
863 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400864 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530865 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530866 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800867 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530868 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
869 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530870 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000871 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530872 log.Fields{
873 "numofTech": tpCount,
874 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
875 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530876 return nil
877}
878
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700879func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530880 portNo uint32, uplinkClassifier map[string]interface{},
881 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700882 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700883 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000884 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530885 log.Fields{
886 "uplinkClassifier": uplinkClassifier,
887 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700888 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
889 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530890 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530891}
892
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700893func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530894 portNo uint32, downlinkClassifier map[string]interface{},
895 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700896 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700897 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000898 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530899 log.Fields{
900 "downlinkClassifier": downlinkClassifier,
901 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400902 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
903 if vlan, exists := downlinkClassifier[VlanVid]; exists {
904 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700905 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000906 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
907 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530908 log.Fields{
909 "flow": logicalFlow,
910 "device-id": f.deviceHandler.device.Id,
911 "onu-id": onuID,
912 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800913 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400914 }
915 }
916 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530917 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400918
Manikkaraj k884c1242019-04-11 16:26:42 +0530919 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700920 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400921 // vlan_vid is a uint32. must be type asserted as such or conversion fails
922 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530923 if ok {
924 downlinkAction[VlanVid] = dlClVid & 0xfff
925 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530926 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530927 "reason": "failed-to-convert-vlanid-classifier",
928 "vlan-id": VlanVid,
929 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530930 }
931
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700932 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
933 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530934}
935
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700936func (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 +0530937 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700938 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
939
940 var inverseDirection string
941 if direction == Upstream {
942 inverseDirection = Downstream
943 } else {
944 inverseDirection = Upstream
945 }
946
Neha Sharma96b7bf22020-06-15 10:37:32 +0000947 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530948 log.Fields{
949 "intf-id": intfID,
950 "onu-id": onuID,
951 "uni-id": uniID,
952 "device-id": f.deviceHandler.device.Id,
953 "classifier": classifier,
954 "action": action,
955 "direction": direction,
956 "alloc-id": allocID,
957 "gemport-id": gemPortID,
958 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700959
960 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000961 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +0530962 log.Fields{
963 "device-id": f.deviceHandler.device.Id,
964 "intf-id": intfID,
965 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800966 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530967 }
David K. Bainbridge794735f2020-02-11 21:01:37 -0800968 classifierProto, err := makeOpenOltClassifierField(classifier)
969 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530970 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530971 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000972 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530973 log.Fields{
974 "classifier": *classifierProto,
975 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +0000976 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -0800977 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530978 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +0530979 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000980 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +0530981 log.Fields{
982 "action": *actionProto,
983 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +0000984 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530985 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530986 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800987 log.Fields{
988 "classifier": classifier,
989 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +0530990 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -0800991 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530992 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700993
994 // Get symmetric flowID if it exists
995 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
996 // symmetric flow earlier
997 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
998 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
999 f.subscriberDataPathFlowIDMapLock.RLock()
1000 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1001 f.subscriberDataPathFlowIDMapLock.RUnlock()
1002
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001003 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001004 OnuId: int32(onuID),
1005 UniId: int32(uniID),
1006 FlowId: logicalFlow.Id,
1007 FlowType: direction,
1008 AllocId: int32(allocID),
1009 NetworkIntfId: int32(networkIntfID),
1010 GemportId: int32(gemPortID),
1011 Classifier: classifierProto,
1012 Action: actionProto,
1013 Priority: int32(logicalFlow.Priority),
1014 Cookie: logicalFlow.Cookie,
1015 PortNo: portNo,
1016 TechProfileId: tpID,
1017 ReplicateFlow: len(pbitToGem) > 0,
1018 PbitToGemport: pbitToGem,
1019 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001020 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001021 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001022 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301023 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001024 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301025 log.Fields{"direction": direction,
1026 "device-id": f.deviceHandler.device.Id,
1027 "flow": flow,
1028 "intf-id": intfID,
1029 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001030 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1031 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1032 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301033 log.Fields{
1034 "flow": flow,
1035 "device-id": f.deviceHandler.device.Id,
1036 "intf-id": intfID,
1037 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001038 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001039
1040 // Update the current flowID to the map
1041 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1042 f.subscriberDataPathFlowIDMapLock.Lock()
1043 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1044 f.subscriberDataPathFlowIDMapLock.Unlock()
1045
David K. Bainbridge794735f2020-02-11 21:01:37 -08001046 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301047}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001048
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001049func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1050 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001051 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301052
Neha Sharma96b7bf22020-06-15 10:37:32 +00001053 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301054 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301055 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001056 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301057 "action": action,
1058 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301060 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301061
1062 // Clear the action map
1063 for k := range action {
1064 delete(action, k)
1065 }
1066
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001067 action[TrapToHost] = true
1068 classifier[UDPSrc] = uint32(68)
1069 classifier[UDPDst] = uint32(67)
1070 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301071
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001072 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001073 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301074 log.Fields{
1075 "device-id": f.deviceHandler.device.Id,
1076 "intf-id": intfID,
1077 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301079 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301080
Neha Sharma96b7bf22020-06-15 10:37:32 +00001081 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301082 log.Fields{
1083 "ul_classifier": classifier,
1084 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001085 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301086 "intf-id": intfID,
1087 "onu-id": onuID,
1088 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301089
David K. Bainbridge794735f2020-02-11 21:01:37 -08001090 classifierProto, err := makeOpenOltClassifierField(classifier)
1091 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301092 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301093 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001094 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001095 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001096 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301097 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301098 }
1099
David K. Bainbridge794735f2020-02-11 21:01:37 -08001100 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001101 OnuId: int32(onuID),
1102 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001103 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001104 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 AllocId: int32(allocID),
1106 NetworkIntfId: int32(networkIntfID),
1107 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301108 Classifier: classifierProto,
1109 Action: actionProto,
1110 Priority: int32(logicalFlow.Priority),
1111 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001112 PortNo: portNo,
1113 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001114 ReplicateFlow: len(pbitToGem) > 0,
1115 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001117 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001118 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001119 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001120 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301121 log.Fields{
1122 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001123 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301124 "intf-id": intfID,
1125 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001126 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1127 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 +05301128 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1129 log.Fields{
1130 "flow": dhcpFlow,
1131 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301132 }
1133
David K. Bainbridge794735f2020-02-11 21:01:37 -08001134 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301135}
1136
Esin Karamanae41e2b2019-12-17 18:13:13 +00001137//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301138func (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 -07001139 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1140 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001141}
1142
1143//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301144func (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 -07001145 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 +00001146
Neha Sharma96b7bf22020-06-15 10:37:32 +00001147 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001148 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301149 return olterrors.NewErrNotFound("nni-interface-id",
1150 log.Fields{
1151 "classifier": classifier,
1152 "action": action,
1153 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001155 }
1156
1157 // Clear the action map
1158 for k := range action {
1159 delete(action, k)
1160 }
1161
1162 action[TrapToHost] = true
1163 classifier[PacketTagType] = SingleTag
1164 delete(classifier, VlanVid)
1165
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001166 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001167 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001168 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001169 }
1170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "ul_classifier": classifier,
1174 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "device-id": f.deviceHandler.device.Id,
1177 "intf-id": intfID,
1178 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 classifierProto, err := makeOpenOltClassifierField(classifier)
1181 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301182 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301185 log.Fields{
1186 "classifier": *classifierProto,
1187 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001188 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001189 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301190 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191 }
1192
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001194 OnuId: int32(onuID),
1195 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001196 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001197 FlowType: Upstream,
1198 AllocId: int32(allocID),
1199 NetworkIntfId: int32(networkIntfID),
1200 GemportId: int32(gemPortID),
1201 Classifier: classifierProto,
1202 Action: actionProto,
1203 Priority: int32(logicalFlow.Priority),
1204 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001205 PortNo: portNo,
1206 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 ReplicateFlow: len(pbitToGem) > 0,
1208 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001209 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001210
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001212 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 -08001213 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001214
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001215 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1216 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 +05301217 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 +00001218 }
1219
David K. Bainbridge794735f2020-02-11 21:01:37 -08001220 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221}
1222
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001224func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1225 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001226 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301228 log.Fields{
1229 "intf-id": intfID,
1230 "onu-id": onuID,
1231 "port-no": portNo,
1232 "alloc-id": allocID,
1233 "gemport-id": gemPortID,
1234 "vlan-id": vlanID,
1235 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301236
1237 uplinkClassifier := make(map[string]interface{})
1238 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301239
manikkaraj kbf256be2019-03-25 00:13:48 +05301240 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001241 uplinkClassifier[EthType] = uint32(EapEthType)
1242 uplinkClassifier[PacketTagType] = SingleTag
1243 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001244 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301245 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001246 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001247 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001248 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301249 "device-id": f.deviceHandler.device.Id,
1250 "onu-id": onuID,
1251 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001252 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301253 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301254 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001255 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301256 log.Fields{
1257 "ul_classifier": uplinkClassifier,
1258 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001259 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301260 "device-id": f.deviceHandler.device.Id,
1261 "intf-id": intfID,
1262 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301263
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1265 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301266 return olterrors.NewErrInvalidValue(log.Fields{
1267 "classifier": uplinkClassifier,
1268 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301269 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001270 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301271 log.Fields{
1272 "classifier": *classifierProto,
1273 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001274 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "action": *actionProto,
1281 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001282 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301283 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301284 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001285 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301286 "action": action,
1287 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301289 }
1290
David K. Bainbridge794735f2020-02-11 21:01:37 -08001291 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001292 OnuId: int32(onuID),
1293 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001294 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001295 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001296 AllocId: int32(allocID),
1297 NetworkIntfId: int32(networkIntfID),
1298 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301299 Classifier: classifierProto,
1300 Action: actionProto,
1301 Priority: int32(logicalFlow.Priority),
1302 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001303 PortNo: portNo,
1304 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001305 ReplicateFlow: len(pbitToGem) > 0,
1306 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001307 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001309 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001311 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301312 log.Fields{
1313 "device-id": f.deviceHandler.device.Id,
1314 "onu-id": onuID,
1315 "intf-id": intfID,
1316 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001317 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1318 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 +05301319 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1320 log.Fields{
1321 "flow": upstreamFlow,
1322 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301323 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001324 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301325}
1326
David K. Bainbridge794735f2020-02-11 21:01:37 -08001327func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001328 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001329
1330 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1331 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1332 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001333 if vlanID != ReservedVlan {
1334 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001335 classifier.OVid = vid
1336 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301337 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001338 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1339 vid := uint32(metadata)
1340 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001341 classifier.IVid = vid
1342 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301343 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301344 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001345 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301346 classifier.OPbits = vlanPcp
1347 } else {
1348 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301349 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001350 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1351 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1352 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1353 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001354 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001355 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1356 classifier.PktTagType = pktTagType
1357
1358 switch pktTagType {
1359 case SingleTag:
1360 case DoubleTag:
1361 case Untagged:
1362 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001363 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301364 }
1365 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001366 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301367}
1368
Gamze Abaka724d0852020-03-18 12:10:24 +00001369func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001370 var actionCmd openoltpb2.ActionCmd
1371 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301372 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001375 if _, ok := actionInfo[VlanPcp]; ok {
1376 action.Cmd.RemarkInnerPbits = true
1377 action.IPbits = actionInfo[VlanPcp].(uint32)
1378 if _, ok := actionInfo[VlanVid]; ok {
1379 action.Cmd.TranslateInnerTag = true
1380 action.IVid = actionInfo[VlanVid].(uint32)
1381 }
1382 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001383 } else if _, ok := actionInfo[PushVlan]; ok {
1384 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301385 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001386 if _, ok := actionInfo[VlanPcp]; ok {
1387 action.OPbits = actionInfo[VlanPcp].(uint32)
1388 action.Cmd.RemarkOuterPbits = true
1389 if _, ok := classifierInfo[VlanVid]; ok {
1390 action.IVid = classifierInfo[VlanVid].(uint32)
1391 action.Cmd.TranslateInnerTag = true
1392 }
1393 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001394 } else if _, ok := actionInfo[TrapToHost]; ok {
1395 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301396 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001397 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301398 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301400}
1401
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001402// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1404 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301405}
1406
Gamze Abakafee36392019-10-03 11:17:24 +00001407// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001408func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301409 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001410 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1411
Gamze Abakafee36392019-10-03 11:17:24 +00001412 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301413 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001414 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301415 // return err
1416 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001417 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001418 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001419 }
1420 return nil
1421}
1422
1423// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301424func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001425 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001426 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001427 }
npujarec5762e2020-01-01 14:08:48 +05301428 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301429 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1430 log.Fields{
1431 "tp-id": tpID,
1432 "uni-port-name": uniPortName,
1433 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001434 }
1435 return nil
1436}
1437
David K. Bainbridge794735f2020-02-11 21:01:37 -08001438func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001439
1440 var intfID uint32
1441 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1442 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1443 */
1444 if deviceFlow.AccessIntfId != -1 {
1445 intfID = uint32(deviceFlow.AccessIntfId)
1446 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001447 // We need to log the valid interface ID.
1448 // 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 +00001449 intfID = uint32(deviceFlow.NetworkIntfId)
1450 }
1451
Neha Sharma96b7bf22020-06-15 10:37:32 +00001452 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301453 "flow": *deviceFlow,
1454 "device-id": f.deviceHandler.device.Id,
1455 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001456 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001457
1458 st, _ := status.FromError(err)
1459 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001460 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001461 "err": err,
1462 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301463 "device-id": f.deviceHandler.device.Id,
1464 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001465 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001467
1468 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001469 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301470 log.Fields{"err": err,
1471 "device-flow": deviceFlow,
1472 "device-id": f.deviceHandler.device.Id,
1473 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001474 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001475 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001476 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301477 log.Fields{
1478 "flow": *deviceFlow,
1479 "device-id": f.deviceHandler.device.Id,
1480 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001481
1482 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1483 if deviceFlow.AccessIntfId != -1 {
1484 // No need to register the flow if it is a trap on nni flow.
1485 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1486 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1487 return err
1488 }
1489 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001490 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001491}
1492
Neha Sharma96b7bf22020-06-15 10:37:32 +00001493func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1494 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301495 log.Fields{
1496 "flow": *deviceFlow,
1497 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001498 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001499 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001500 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001501 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301502 log.Fields{
1503 "err": err,
1504 "deviceFlow": deviceFlow,
1505 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001506 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001507 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001508 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001509 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001510
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001511 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001512 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001513 "of-flow-id": ofFlowID,
1514 "flow": *deviceFlow,
1515 "device-id": f.deviceHandler.device.Id,
1516 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001517 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301518}
1519
David K. Bainbridge794735f2020-02-11 21:01:37 -08001520func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001521
1522 classifierInfo := make(map[string]interface{})
1523 actionInfo := make(map[string]interface{})
1524
1525 classifierInfo[EthType] = uint32(LldpEthType)
1526 classifierInfo[PacketTagType] = Untagged
1527 actionInfo[TrapToHost] = true
1528
1529 // LLDP flow is installed to trap LLDP packets on the NNI port.
1530 // We manage flow_id resource pool on per PON port basis.
1531 // Since this situation is tricky, as a hack, we pass the NNI port
1532 // index (network_intf_id) as PON port Index for the flow_id resource
1533 // pool. Also, there is no ONU Id available for trapping LLDP packets
1534 // on NNI port, use onu_id as -1 (invalid)
1535 // ****************** CAVEAT *******************
1536 // This logic works if the NNI Port Id falls within the same valid
1537 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1538 // we need to have a re-look at this.
1539 // *********************************************
1540
1541 var onuID = -1
1542 var uniID = -1
1543 var gemPortID = -1
1544
Neha Sharma96b7bf22020-06-15 10:37:32 +00001545 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001546 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301547 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001548 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001549 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001550 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001551 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001552 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001553
David K. Bainbridge794735f2020-02-11 21:01:37 -08001554 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1555 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301556 return olterrors.NewErrInvalidValue(
1557 log.Fields{
1558 "classifier": classifierInfo,
1559 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001560 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001561 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301562 log.Fields{
1563 "classifier": *classifierProto,
1564 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001565 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001566 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301567 return olterrors.NewErrInvalidValue(
1568 log.Fields{
1569 "action": actionInfo,
1570 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001572 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301573 log.Fields{
1574 "action": *actionProto,
1575 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001576
1577 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1578 OnuId: int32(onuID), // OnuId not required
1579 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001580 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001581 FlowType: Downstream,
1582 NetworkIntfId: int32(networkInterfaceID),
1583 GemportId: int32(gemPortID),
1584 Classifier: classifierProto,
1585 Action: actionProto,
1586 Priority: int32(flow.Priority),
1587 Cookie: flow.Cookie,
1588 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001589 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001590 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301591 log.Fields{
1592 "flow": downstreamflow,
1593 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001594 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001595 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301596 log.Fields{
1597 "device-id": f.deviceHandler.device.Id,
1598 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001599 "flow-id": flow.Id})
1600 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1601 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1602 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301603 log.Fields{
1604 "flow": downstreamflow,
1605 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001606 }
1607 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301608}
1609
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001610func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1611 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001612}
1613
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001614//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001616 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1617 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1618 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001619 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301620 log.Fields{
1621 "intf-id": intfID,
1622 "onu-id": onuID,
1623 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001625 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301626 return nil, olterrors.NewErrNotFound("onu-child-device",
1627 log.Fields{
1628 "onu-id": onuID,
1629 "intf-id": intfID,
1630 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001631 }
1632 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1633 //better to ad the device to cache here.
1634 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1635 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001636 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301637 log.Fields{
1638 "intf-id": intfID,
1639 "onu-id": onuID,
1640 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001641 }
1642
1643 return onuDev.(*OnuDevice), nil
1644}
1645
1646//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001647func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1648 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "pon-port": intfID,
1651 "onu-id": onuID,
1652 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001653 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301656 return nil, olterrors.NewErrNotFound("onu",
1657 log.Fields{
1658 "interface-id": parentPortNo,
1659 "onu-id": onuID,
1660 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001661 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301662 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301664 log.Fields{
1665 "device-id": f.deviceHandler.device.Id,
1666 "child_device_id": onuDevice.Id,
1667 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301668 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301669}
1670
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1672 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301673 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001674 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301675 log.Fields{
1676 "intf-id": intfID,
1677 "onu-id": onuID,
1678 "uni-id": uniID,
1679 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001680 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301681 }
1682
1683 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301685 log.Fields{
1686 "msg": *delGemPortMsg,
1687 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001688 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301689 delGemPortMsg,
1690 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001691 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001692 onuDev.deviceType,
1693 onuDev.deviceID,
1694 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301695 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1696 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001697 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301698 "to-adapter": onuDev.deviceType,
1699 "onu-id": onuDev.deviceID,
1700 "proxyDeviceID": onuDev.proxyDeviceID,
1701 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001703 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301704 log.Fields{
1705 "msg": delGemPortMsg,
1706 "from-adapter": f.deviceHandler.device.Type,
1707 "to-adapter": onuDev.deviceType,
1708 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301709 return nil
1710}
1711
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1713 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301714 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001715 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301716 log.Fields{
1717 "intf-id": intfID,
1718 "onu-id": onuID,
1719 "uni-id": uniID,
1720 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001721 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301722 }
1723
1724 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301726 log.Fields{
1727 "msg": *delTcontMsg,
1728 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001729 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301730 delTcontMsg,
1731 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001732 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001733 onuDev.deviceType,
1734 onuDev.deviceID,
1735 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301736 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1737 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001738 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301739 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1740 "proxyDeviceID": onuDev.proxyDeviceID,
1741 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301742 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001743 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301744 log.Fields{
1745 "msg": delTcontMsg,
1746 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301747 return nil
1748}
1749
Girish Gowdrac3037402020-01-22 20:29:53 +05301750// Once the gemport is released for a given onu, it also has to be cleared from local cache
1751// which was used for deriving the gemport->logicalPortNo during packet-in.
1752// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1753// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001755
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001756 f.onuGemInfoLock.Lock()
1757 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001758
Neha Sharma96b7bf22020-06-15 10:37:32 +00001759 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301760 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001761 "gem-port-id": gemPortID,
1762 "intf-id": intfID,
1763 "onu-id": onuID,
1764 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001765 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001766
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001767 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001768deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001769 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301770 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001771 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301772 // If the gemport is found, delete it from local cache.
1773 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001774 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1775 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "deletedgemport-id": gemPortID,
1781 "gemports": onu.GemPorts,
1782 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001783 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301784 }
1785 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001786 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301787 }
1788 }
1789}
1790
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301791//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001792// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301793func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001794 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001795
Neha Sharma96b7bf22020-06-15 10:37:32 +00001796 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001797 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301798 return olterrors.NewErrNotFound("tp-id",
1799 log.Fields{
1800 "flow": flow,
1801 "intf": Intf,
1802 "onu-id": onuID,
1803 "uni-id": uniID,
1804 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001805 }
Gamze Abakafee36392019-10-03 11:17:24 +00001806
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001807 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1808 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1809 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1810 log.Fields{
1811 "tpPath": tpPath,
1812 "device-id": f.deviceHandler.device.Id})
1813 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1814 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1815 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1816 log.Fields{
1817 "tp-id": tpID,
1818 "path": tpPath}, err)
1819 }
1820
1821 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1822
1823 if used {
1824 f.flowsUsedByGemPortKey.Lock()
1825 defer f.flowsUsedByGemPortKey.Unlock()
1826
1827 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1828 for i, flowIDinMap := range flowIDs {
1829 if flowIDinMap == flowID {
1830 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1831 // everytime flowsUsedByGemPort cache is updated the same should be updated
1832 // in kv store by calling UpdateFlowIDsForGem
1833 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1834 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1835 return err
1836 }
1837 break
1838 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001839 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001840 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1841 log.Fields{
1842 "gemport-id": gemPortID,
1843 "usedByFlows": flowIDs,
1844 "device-id": f.deviceHandler.device.Id})
1845 return nil
1846 }
1847 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1848 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1849 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1850 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1851 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
1852 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
1853 f.onuIdsLock.Lock() // TODO: What is this lock?
1854
1855 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1856 // by calling DeleteFlowIDsForGem
1857 f.flowsUsedByGemPortKey.Lock()
1858 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1859 f.flowsUsedByGemPortKey.Unlock()
1860 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1861 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1862
1863 f.onuIdsLock.Unlock()
1864
1865 // Delete the gem port on the ONU.
1866 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1867 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1868 log.Fields{
1869 "err": err,
1870 "intf": Intf,
1871 "onu-id": onuID,
1872 "uni-id": uniID,
1873 "device-id": f.deviceHandler.device.Id,
1874 "gemport-id": gemPortID})
1875 }
1876 switch techprofileInst := techprofileInst.(type) {
1877 case *tp.TechProfile:
1878 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1879 if !ok {
1880 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1881 logger.Warn(ctx, err)
1882 }
1883 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1884 logger.Warn(ctx, err)
1885 }
1886 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 {
1887 logger.Warn(ctx, err)
1888 }
1889 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 {
1890 logger.Warn(ctx, err)
1891 }
1892 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1893 // Delete the TCONT on the ONU.
1894 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1895 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1896 log.Fields{
1897 "intf": Intf,
1898 "onu-id": onuID,
1899 "uni-id": uniID,
1900 "device-id": f.deviceHandler.device.Id,
1901 "alloc-id": techprofileInst.UsScheduler.AllocID})
1902 }
1903 }
1904 case *tp.EponProfile:
1905 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1906 logger.Warn(ctx, err)
1907 }
1908 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1909 logger.Warn(ctx, err)
1910 }
1911 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1912 // Delete the TCONT on the ONU.
1913 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1914 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301915 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001916 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301917 "onu-id": onuID,
1918 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919 "device-id": f.deviceHandler.device.Id,
1920 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001921 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001922 default:
1923 logger.Errorw(ctx, "error-unknown-tech",
1924 log.Fields{
1925 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001926 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301928 return nil
1929}
1930
David K. Bainbridge794735f2020-02-11 21:01:37 -08001931// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001932func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001933 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001934 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301935 log.Fields{
1936 "flowDirection": flowDirection,
1937 "flow": *flow,
1938 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001939
1940 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001941 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00001942 }
1943
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301944 classifierInfo := make(map[string]interface{})
1945
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301947 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001948 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001949 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301950 }
Girish Gowdra3d633032019-12-10 16:37:05 +05301951
David K. Bainbridge794735f2020-02-11 21:01:37 -08001952 onuID := int32(onu)
1953 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301954
1955 for _, field := range flows.GetOfbFields(flow) {
1956 if field.Type == flows.IP_PROTO {
1957 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00001958 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301959 }
1960 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001961 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05301962 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001963 "flow-id": flow.Id,
1964 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301965 "onu-id": onuID,
1966 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301967
1968 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
1969 onuID = -1
1970 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00001971 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
1972 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001973 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001974 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001975 log.Fields{
1976 "port-number": inPort,
1977 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001978 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08001979 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301980 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001981 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
1982 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})
1983 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
1984 }
1985 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
1986 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
1987 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
1988 return err
1989 }
1990 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
1991 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
1992 return err
1993 }
1994 if !flowInfo.Flow.ReplicateFlow {
1995 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
1996 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
1997 "flow-id": flow.Id,
1998 "stored-flow": flowInfo.Flow,
1999 "device-id": f.deviceHandler.device.Id,
2000 "stored-flow-id": flowInfo.Flow.FlowId,
2001 "onu-id": onuID,
2002 "intf": Intf,
2003 })
2004 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302005 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002006 } else {
2007 gems := make([]uint32, 0)
2008 for _, gem := range flowInfo.Flow.PbitToGemport {
2009 gems = appendUnique32bit(gems, gem)
2010 }
2011 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2012 for _, gem := range gems {
2013 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
2014 logger.Error(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002015 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002016 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002017 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002018 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002019 "onu-id": onuID,
2020 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002021 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002022 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002023 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302024 }
2025 }
2026 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027
2028 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2029 if isDatapathFlow(flow) {
2030 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2031 var inverseDirection string
2032 if flowDirection == Upstream {
2033 inverseDirection = Downstream
2034 } else {
2035 inverseDirection = Upstream
2036 }
2037
2038 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002039 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002040 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002041 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002042 }
2043 }
2044 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002045}
2046
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002047//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002048func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302051 var direction string
2052 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002053
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302054 for _, action := range flows.GetActions(flow) {
2055 if action.Type == flows.OUTPUT {
2056 if out := action.GetOutput(); out != nil {
2057 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002058 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302059 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002060 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002061 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002062 }
2063 }
2064 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002065
2066 if flows.HasGroup(flow) {
2067 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002068 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002069 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302070 direction = Upstream
2071 } else {
2072 direction = Downstream
2073 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302074
Girish Gowdracefae192020-03-19 18:14:10 -07002075 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002076 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002077
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002078 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002079}
2080
Esin Karamanae41e2b2019-12-17 18:13:13 +00002081//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2082func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2083 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2084 if ethType, ok := classifierInfo[EthType]; ok {
2085 if ethType.(uint32) == IPv4EthType {
2086 if ipProto, ok := classifierInfo[IPProto]; ok {
2087 if ipProto.(uint32) == IgmpProto {
2088 return true
2089 }
2090 }
2091 }
2092 }
2093 }
2094 return false
2095}
2096
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002097// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2098func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2099 // Step1 : Fill flowControlBlock
2100 // Step2 : Push the flowControlBlock to ONU channel
2101 // Step3 : Wait on response channel for response
2102 // Step4 : Return error value
2103 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2104 errChan := make(chan error)
2105 flowCb := flowControlBlock{
2106 ctx: ctx,
2107 addFlow: addFlow,
2108 flow: flow,
2109 flowMetadata: flowMetadata,
2110 errChan: &errChan,
2111 }
2112 inPort, outPort := getPorts(flow)
2113 var onuID uint32
2114 if inPort != InvalidPort && outPort != InvalidPort {
2115 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2116 }
2117 // inPort or outPort is InvalidPort for trap-from-nni flows.
2118 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2119 // Send the flowCb on the ONU flow channel
2120 f.incomingFlows[onuID] <- flowCb
2121 // Wait on the channel for flow handlers return value
2122 err := <-errChan
2123 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2124 return err
2125}
2126
2127// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2128// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2129func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2130 for {
2131 // block on the channel to receive an incoming flow
2132 // process the flow completely before proceeding to handle the next flow
2133 flowCb := <-subscriberFlowChannel
2134 if flowCb.addFlow {
2135 logger.Debugw(flowCb.ctx, "adding-flow",
2136 log.Fields{"device-id": f.deviceHandler.device.Id,
2137 "flowToAdd": flowCb.flow})
2138 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2139 // Pass the return value over the return channel
2140 *flowCb.errChan <- err
2141 } else {
2142 logger.Debugw(flowCb.ctx, "removing-flow",
2143 log.Fields{"device-id": f.deviceHandler.device.Id,
2144 "flowToRemove": flowCb.flow})
2145 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2146 // Pass the return value over the return channel
2147 *flowCb.errChan <- err
2148 }
2149 }
2150}
2151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002152// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302153// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002154func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002155 classifierInfo := make(map[string]interface{})
2156 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002157 var UsMeterID uint32
2158 var DsMeterID uint32
2159
Neha Sharma96b7bf22020-06-15 10:37:32 +00002160 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302161 log.Fields{
2162 "flow": flow,
2163 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002165
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002167 if err != nil {
2168 // Error logging is already done in the called function
2169 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002170 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302171 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002172
Esin Karamanccb714b2019-11-29 15:02:06 +00002173 if flows.HasGroup(flow) {
2174 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002175 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002176 }
2177
manikkaraj k17652a72019-05-06 09:06:36 -04002178 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002179 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002180 if err != nil {
2181 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002182 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002183 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002184
Neha Sharma96b7bf22020-06-15 10:37:32 +00002185 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302186 log.Fields{
2187 "classifierinfo_inport": classifierInfo[InPort],
2188 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002189 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002190
Humera Kouser94d7a842019-08-25 19:04:32 -04002191 if ethType, ok := classifierInfo[EthType]; ok {
2192 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002193 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002194 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002195 }
2196 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002197 if ipProto, ok := classifierInfo[IPProto]; ok {
2198 if ipProto.(uint32) == IPProtoDhcp {
2199 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302200 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002201 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002202 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002203 }
2204 }
2205 }
2206 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002207 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002209 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002210 }
A R Karthick1f85b802019-10-11 05:06:05 +00002211
npujarec5762e2020-01-01 14:08:48 +05302212 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002213
Neha Sharma96b7bf22020-06-15 10:37:32 +00002214 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002215 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302216 return olterrors.NewErrNotFound("tpid-for-flow",
2217 log.Fields{
2218 "flow": flow,
2219 "intf-id": IntfID,
2220 "onu-id": onuID,
2221 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002222 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302224 log.Fields{
2225 "tp-id": TpID,
2226 "intf-id": intfID,
2227 "onu-id": onuID,
2228 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002229 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002230 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002231 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002232 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002233 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002234 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002235
2236 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002237 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002238}
Girish Gowdra3d633032019-12-10 16:37:05 +05302239
Esin Karamanccb714b2019-11-29 15:02:06 +00002240// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002241func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002242 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002243 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302244 "classifier-info": classifierInfo,
2245 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002246
Esin Karaman65409d82020-03-18 10:58:18 +00002247 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002248 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002249 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002250 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002251
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002252 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002253
David K. Bainbridge794735f2020-02-11 21:01:37 -08002254 onuID := NoneOnuID
2255 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002256
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002257 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002258 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002259 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002260 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002261 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2262 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002263 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002264 }
2265 groupID := actionInfo[GroupID].(uint32)
2266 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002267 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002268 FlowType: Multicast,
2269 NetworkIntfId: int32(networkInterfaceID),
2270 GroupId: groupID,
2271 Classifier: classifierProto,
2272 Priority: int32(flow.Priority),
2273 Cookie: flow.Cookie}
2274
Kent Hagermane6ff1012020-07-14 15:07:53 -04002275 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002276 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002278 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002279 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002280 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002281 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002282 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002283 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002284 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002285 //cached group can be removed now
2286 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2287 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2288 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002289 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002290
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002291 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2292 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2293 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002294 }
2295 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002296}
2297
Esin Karaman65409d82020-03-18 10:58:18 +00002298//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2299func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2300 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002301 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002302 if err != nil {
2303 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2304 }
2305 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002306 }
Esin Karaman65409d82020-03-18 10:58:18 +00002307 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302308 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002309 if e == nil && len(nniPorts) > 0 {
2310 return nniPorts[0], nil
2311 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302312 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002313}
2314
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002315//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002316func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002317
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302319 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002320 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302321 log.Fields{
2322 "intf-id": intfID,
2323 "onu-id": onuID,
2324 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002325 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302326 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002327 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002328
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002330 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002332 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002333 tpDownloadMsg,
2334 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002335 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002336 onuDev.deviceType,
2337 onuDev.deviceID,
2338 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002339 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302340 return olterrors.NewErrCommunication("send-techprofile-download-request",
2341 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002342 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302343 "to-adapter": onuDev.deviceType,
2344 "onu-id": onuDev.deviceID,
2345 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002346 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002347 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302348 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302349}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002350
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302351//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002352func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302353
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002354 f.onuGemInfoLock.Lock()
2355 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002356 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002357 // If the ONU already exists in onuGemInfo list, nothing to do
2358 for _, onu := range onugem {
2359 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2360 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2361 log.Fields{"onuID": onuID,
2362 "serialNum": serialNum})
2363 return nil
2364 }
2365 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002366
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302367 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002368 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002369 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002370 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302371 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302373 log.Fields{
2374 "intf-id": intfID,
2375 "onu-id": onuID,
2376 "serial-num": serialNum,
2377 "onu": onu,
2378 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002379 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002380}
2381
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302382//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302383func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002384
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002385 f.onuGemInfoLock.Lock()
2386 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002387
Neha Sharma96b7bf22020-06-15 10:37:32 +00002388 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302389 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002390 "gem-port-id": gemPort,
2391 "intf-id": intfID,
2392 "onu-id": onuID,
2393 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002394 "onu-gem": f.onuGemInfo})
2395 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302396 // update the gem to the local cache as well as to kv strore
2397 for idx, onu := range onugem {
2398 if onu.OnuID == onuID {
2399 // check if gem already exists , else update the cache and kvstore
2400 for _, gem := range onu.GemPorts {
2401 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302403 log.Fields{
2404 "gem": gemPort,
2405 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302406 return
2407 }
2408 }
2409 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002410 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002411 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302412 }
2413 }
npujarec5762e2020-01-01 14:08:48 +05302414 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302415 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302417 log.Fields{
2418 "intf-id": intfID,
2419 "onu-id": onuID,
2420 "gemPort": gemPort,
2421 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002422 return
2423 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002424 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302425 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002426 "gem-port-id": gemPort,
2427 "intf-id": intfID,
2428 "onu-id": onuID,
2429 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002430 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002431}
2432
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002433//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 +00002434func (f *OpenOltFlowMgr) getOnuIDfromGemPortMap(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302435
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002436 f.onuGemInfoLock.RLock()
2437 defer f.onuGemInfoLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302438
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002439 logger.Debugw(ctx, "getting-onu-id-from-gem-port-and-pon-port",
Shrey Baid26912972020-04-16 21:02:31 +05302440 log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002441 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002442 "onu-geminfo": f.onuGemInfo,
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002443 "intf-id": intfID,
2444 "gemport-id": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302445 // get onuid from the onugem info cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002446 onugem := f.onuGemInfo
Matteo Scandolod625b4c2020-04-02 16:16:01 -07002447
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302448 for _, onu := range onugem {
2449 for _, gem := range onu.GemPorts {
2450 if gem == gemPortID {
2451 return onu.OnuID, nil
2452 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002453 }
2454 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002455 logger.Errorw(ctx, "onu-id-from-gem-port-not-found", log.Fields{
2456 "gem-port-id": gemPortID,
2457 "interface-id": intfID,
Kent Hagermane6ff1012020-07-14 15:07:53 -04002458 "all-gems-on-port": onugem,
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002459 })
Thomas Lee S94109f12020-03-03 16:39:29 +05302460 return uint32(0), olterrors.NewErrNotFound("onu-id", log.Fields{
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002461 "interface-id": intfID,
2462 "gem-port-id": gemPortID},
Girish Kumarf26e4882020-03-05 06:49:10 +00002463 nil)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002464}
2465
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002466//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302467func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002468 var logicalPortNum uint32
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002469 var onuID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002470 var err error
2471
2472 if packetIn.IntfType == "pon" {
2473 // packet indication does not have serial number , so sending as nil
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 if onuID, err = f.getOnuIDfromGemPortMap(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002475 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002476 return logicalPortNum, err
2477 }
2478 if packetIn.PortNo != 0 {
2479 logicalPortNum = packetIn.PortNo
2480 } else {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002481 uniID := uint32(0) // FIXME - multi-uni support
Neha Sharma96b7bf22020-06-15 10:37:32 +00002482 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002483 }
2484 // 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 +00002485 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002486 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002487 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002488 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002489
2490 if logger.V(log.DebugLevel) {
2491 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2492 log.Fields{
2493 "logical-port-num": logicalPortNum,
2494 "intf-type": packetIn.IntfType,
2495 "packet": hex.EncodeToString(packetIn.Pkt),
2496 })
2497 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002498 return logicalPortNum, nil
2499}
2500
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002501//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002502func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002503 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002504
2505 ctag, priority, err := getCTagFromPacket(ctx, packet)
2506 if err != nil {
2507 return 0, err
2508 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302509
Esin Karaman7fb80c22020-07-16 14:23:33 +00002510 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002511 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002512 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002513 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002514 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302515 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302517 log.Fields{
2518 "pktinkey": pktInkey,
2519 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002520
2521 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002522 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302523 //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 +00002524 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302525 if err == nil {
2526 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002527 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302528 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002529 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002530 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302531 log.Fields{
2532 "pktinkey": pktInkey,
2533 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302534 return gemPortID, nil
2535 }
2536 }
Shrey Baid26912972020-04-16 21:02:31 +05302537 return uint32(0), olterrors.NewErrNotFound("gem-port",
2538 log.Fields{
2539 "pktinkey": pktInkey,
2540 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002541
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002542}
2543
David K. Bainbridge794735f2020-02-11 21:01:37 -08002544func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002545 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002546 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002547 classifier[PacketTagType] = DoubleTag
2548 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549 /* We manage flowId resource pool on per PON port basis.
2550 Since this situation is tricky, as a hack, we pass the NNI port
2551 index (network_intf_id) as PON port Index for the flowId resource
2552 pool. Also, there is no ONU Id available for trapping DHCP packets
2553 on NNI port, use onu_id as -1 (invalid)
2554 ****************** CAVEAT *******************
2555 This logic works if the NNI Port Id falls within the same valid
2556 range of PON Port Ids. If this doesn't work for some OLT Vendor
2557 we need to have a re-look at this.
2558 *********************************************
2559 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002560 onuID := -1
2561 uniID := -1
2562 gemPortID := -1
2563 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002564 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302565 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302566 return olterrors.NewErrNotFound("nni-intreface-id",
2567 log.Fields{
2568 "classifier": classifier,
2569 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002570 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302571 }
2572
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002573 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002574 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002575 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002576 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002577
David K. Bainbridge794735f2020-02-11 21:01:37 -08002578 classifierProto, err := makeOpenOltClassifierField(classifier)
2579 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002580 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002582 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002583 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002584 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002585 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002587 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002588 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2589 OnuId: int32(onuID), // OnuId not required
2590 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002591 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002592 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002593 AllocId: int32(allocID), // AllocId not used
2594 NetworkIntfId: int32(networkInterfaceID),
2595 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596 Classifier: classifierProto,
2597 Action: actionProto,
2598 Priority: int32(logicalFlow.Priority),
2599 Cookie: logicalFlow.Cookie,
2600 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002601 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002602 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002605 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2606 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2607 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002608 }
2609 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002610}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002611
Esin Karamanae41e2b2019-12-17 18:13:13 +00002612//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2613func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2614 var packetType string
2615 ovid, ivid := false, false
2616 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2617 vid := vlanID & VlanvIDMask
2618 if vid != ReservedVlan {
2619 ovid = true
2620 }
2621 }
2622 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2623 vid := uint32(metadata)
2624 if vid != ReservedVlan {
2625 ivid = true
2626 }
2627 }
2628 if ovid && ivid {
2629 packetType = DoubleTag
2630 } else if !ovid && !ivid {
2631 packetType = Untagged
2632 } else {
2633 packetType = SingleTag
2634 }
2635 return packetType
2636}
2637
2638//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002639func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002640 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002641 action := make(map[string]interface{})
2642 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2643 action[TrapToHost] = true
2644 /* We manage flowId resource pool on per PON port basis.
2645 Since this situation is tricky, as a hack, we pass the NNI port
2646 index (network_intf_id) as PON port Index for the flowId resource
2647 pool. Also, there is no ONU Id available for trapping packets
2648 on NNI port, use onu_id as -1 (invalid)
2649 ****************** CAVEAT *******************
2650 This logic works if the NNI Port Id falls within the same valid
2651 range of PON Port Ids. If this doesn't work for some OLT Vendor
2652 we need to have a re-look at this.
2653 *********************************************
2654 */
2655 onuID := -1
2656 uniID := -1
2657 gemPortID := -1
2658 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002659 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002660 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302661 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 "classifier": classifier,
2663 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002664 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002665 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002666 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002669 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002670
David K. Bainbridge794735f2020-02-11 21:01:37 -08002671 classifierProto, err := makeOpenOltClassifierField(classifier)
2672 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002673 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002674 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002675 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002676 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002677 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002678 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002680 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002681 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2682 OnuId: int32(onuID), // OnuId not required
2683 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002684 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002685 FlowType: Downstream,
2686 AllocId: int32(allocID), // AllocId not used
2687 NetworkIntfId: int32(networkInterfaceID),
2688 GemportId: int32(gemPortID), // GemportId not used
2689 Classifier: classifierProto,
2690 Action: actionProto,
2691 Priority: int32(logicalFlow.Priority),
2692 Cookie: logicalFlow.Cookie,
2693 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002694 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002695 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002696 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002697 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002698 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2699 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2700 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002701 }
2702 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002703}
2704
salmansiddiqui7ac62132019-08-22 03:58:50 +00002705func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2706 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302707 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002708 }
2709 if Dir == tp_pb.Direction_UPSTREAM {
2710 return "upstream", nil
2711 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2712 return "downstream", nil
2713 }
2714 return "", nil
2715}
2716
Kent Hagermane6ff1012020-07-14 15:07:53 -04002717// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302718func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002719 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002720 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002721 var gemPort uint32
2722 intfID := args[IntfID]
2723 onuID := args[OnuID]
2724 uniID := args[UniID]
2725 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002726 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002727 pbitToGem := make(map[uint32]uint32)
2728
2729 if len(gemPorts) == 1 {
2730 // If there is only single gemport use that and do not populate pbitToGem map
2731 gemPort = gemPorts[0]
2732 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2733 for idx, gemID := range gemPorts {
2734 switch TpInst := TpInst.(type) {
2735 case *tp.TechProfile:
2736 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2737 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2738 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2739 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2740 // this pcp bit traffic.
2741 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2742 if pbitSet == pbit1 {
2743 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2744 pbitToGem[pcp] = gemID
2745 }
2746 }
2747 default:
2748 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2749 return
2750 }
2751 }
2752 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2753 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2754 tp_pb.Direction_UPSTREAM,
2755 pcp.(uint32))
2756 }
2757
salmansiddiqui7ac62132019-08-22 03:58:50 +00002758 if ipProto, ok := classifierInfo[IPProto]; ok {
2759 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002761 "tp-id": tpID,
2762 "alloc-id": allocID,
2763 "intf-id": intfID,
2764 "onu-id": onuID,
2765 "uni-id": uniID,
2766 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002767 //Adding DHCP upstream flow
2768 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2769 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002770 }
2771
Girish Gowdra32625212020-04-29 11:26:35 -07002772 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002773 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302774 log.Fields{
2775 "intf-id": intfID,
2776 "onu-id": onuID,
2777 "uni-id": uniID,
2778 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002779 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2780 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002781 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002782 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002783 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002784 return
2785 }
2786 } else if ethType, ok := classifierInfo[EthType]; ok {
2787 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002788 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002789 "intf-id": intfID,
2790 "onu-id": onuID,
2791 "uni-id": uniID,
2792 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002793 var vlanID uint32
2794 if val, ok := classifierInfo[VlanVid]; ok {
2795 vlanID = (val.(uint32)) & VlanvIDMask
2796 } else {
2797 vlanID = DefaultMgmtVlan
2798 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002799 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2800 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002801 }
2802 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002803 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002804 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002805 "intf-id": intfID,
2806 "onu-id": onuID,
2807 "uni-id": uniID,
2808 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002809 //Adding HSIA upstream flow
2810 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2811 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002812 }
2813 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002814 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002815 "intf-id": intfID,
2816 "onu-id": onuID,
2817 "uni-id": uniID,
2818 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002819 //Adding HSIA downstream flow
2820 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2821 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002822 }
2823 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002824 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302825 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002826 "intf-id": intfID,
2827 "onu-id": onuID,
2828 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302829 "classifier": classifierInfo,
2830 "action": actionInfo,
2831 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002832 return
2833 }
2834 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002835 go func() {
2836 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2837 logger.Warn(ctx, err)
2838 }
2839 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002840}
2841
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002842func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2843 f.flowsUsedByGemPortKey.RLock()
2844 flowIDList := f.flowsUsedByGemPort[gemPortID]
2845 f.flowsUsedByGemPortKey.RUnlock()
2846 return len(flowIDList) > 1
2847
Gamze Abakafee36392019-10-03 11:17:24 +00002848}
2849
npujarec5762e2020-01-01 14:08:48 +05302850func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2851 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002852 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2853 for _, currentGemPort := range currentGemPorts {
2854 for _, tpGemPort := range tpGemPorts {
2855 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2856 return true, currentGemPort
2857 }
2858 }
2859 }
Girish Gowdra54934262019-11-13 14:19:55 +05302860 if tpInst.InstanceCtrl.Onu == "single-instance" {
2861 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002862 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002863 logger.Warn(ctx, err)
2864 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002865 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002866 logger.Warn(ctx, err)
2867 }
Girish Gowdra54934262019-11-13 14:19:55 +05302868
2869 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2870 // still be used on other uni ports.
2871 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2872 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002873 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002874 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302875 for i := 0; i < len(tpInstances); i++ {
2876 tpI := tpInstances[i]
2877 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302878 for _, tpGemPort := range tpGemPorts {
2879 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002880 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302881 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302882 }
2883 }
2884 }
2885 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002886 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002887 return false, 0
2888}
2889
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002891 for _, field := range flows.GetOfbFields(flow) {
2892 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002895 } else if field.Type == flows.ETH_DST {
2896 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002897 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002898 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002899 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002900 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002901 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002902 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002903 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002904 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302905 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002906 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002907 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002910 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002911 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002912 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002913 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002914 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002916 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002917 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002918 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002919 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002921 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002922 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002923 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002924 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002925 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002927 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 return
2931 }
2932 }
2933}
2934
Neha Sharma96b7bf22020-06-15 10:37:32 +00002935func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002936 for _, action := range flows.GetActions(flow) {
2937 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002939 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002940 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002942 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002943 }
Scott Baker355d1742019-10-24 10:57:52 -07002944 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002946 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002947 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 if out := action.GetPush(); out != nil {
2949 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002950 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 } else {
2952 actionInfo[PushVlan] = true
2953 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002954 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302955 log.Fields{
2956 "push-tpid": actionInfo[TPID].(uint32),
2957 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 }
2959 }
Scott Baker355d1742019-10-24 10:57:52 -07002960 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 if out := action.GetSetField(); out != nil {
2962 if field := out.GetField(); field != nil {
2963 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002964 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002966 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2967 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002968 }
2969 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002970 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002971 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002973 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974 }
2975 }
2976 return nil
2977}
2978
Neha Sharma96b7bf22020-06-15 10:37:32 +00002979func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00002980 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00002981 fieldtype := ofbField.GetType()
2982 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00002983 if vlan := ofbField.GetVlanVid(); vlan != 0 {
2984 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002986 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002987 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00002988 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00002989 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
2990 pcp := ofbField.GetVlanPcp()
2991 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00002992 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002993 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00002995 }
2996 }
2997}
2998
Neha Sharma96b7bf22020-06-15 10:37:32 +00002999func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003000 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003002 } else {
3003 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003005 }
3006}
3007
Neha Sharma96b7bf22020-06-15 10:37:32 +00003008func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003009 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3012 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003013 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303016 log.Fields{
3017 "newinport": classifierInfo[InPort].(uint32),
3018 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303020 return olterrors.NewErrNotFound("child-in-port",
3021 log.Fields{
3022 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3023 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 }
3025 }
3026 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003028 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003029 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003030 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003031 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303033 log.Fields{
3034 "newoutport": actionInfo[Output].(uint32),
3035 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303037 return olterrors.NewErrNotFound("out-port",
3038 log.Fields{
3039 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3040 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 }
3042 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3043 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003044 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003046 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303047 log.Fields{
3048 "newinport": actionInfo[Output].(uint32),
3049 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303051 return olterrors.NewErrNotFound("nni-port",
3052 log.Fields{
3053 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3054 "in-port": classifierInfo[InPort].(uint32),
3055 "out-port": actionInfo[Output].(uint32),
3056 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003057 }
3058 }
3059 }
3060 return nil
3061}
Gamze Abakafee36392019-10-03 11:17:24 +00003062
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003064 /* Metadata 8 bytes:
3065 Most Significant 2 Bytes = Inner VLAN
3066 Next 2 Bytes = Tech Profile ID(TPID)
3067 Least Significant 4 Bytes = Port ID
3068 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3069 subscriber related flows.
3070 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003072 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003073 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003074 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003076 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003077}
3078
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003079func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3080 for _, sliceElement := range slice {
3081 if sliceElement == item {
3082 return slice
3083 }
3084 }
3085 return append(slice, item)
3086}
3087
3088func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003089 for _, sliceElement := range slice {
3090 if sliceElement == item {
3091 return slice
3092 }
3093 }
3094 return append(slice, item)
3095}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303096
3097// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303099
3100 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3101 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003102 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003103 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003104 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003105 log.Fields{
3106 "port-number": action[Output].(uint32),
3107 "error": err})
3108 return uint32(0), err
3109 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003110 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303111 return intfID, nil
3112 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003114 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003115 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003116 log.Fields{
3117 "port-number": action[Output].(uint32),
3118 "error": err})
3119 return uint32(0), err
3120 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303122 return intfID, nil
3123 }
3124 return uint32(0), nil
3125}
3126
3127// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003128func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3129 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3130 if err != nil {
3131 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3132 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3133 return
3134 }
3135 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003136
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003137 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003138 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003139 f.packetInGemPortLock.RUnlock()
3140
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303141 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003142 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003143 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 +05303144 log.Fields{
3145 "pktinkey": pktInkey,
3146 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003147 return
3148 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303149 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003150 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003151 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003152 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003153
npujarec5762e2020-01-01 14:08:48 +05303154 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003155 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 +05303156 log.Fields{
3157 "pktinkey": pktInkey,
3158 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303159}
3160
Esin Karaman7fb80c22020-07-16 14:23:33 +00003161//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3162func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3163 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003164 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003165 return 0, 0, errors.New("invalid packet length")
3166 }
3167 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3168 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3169
3170 var index int8
3171 if outerEthType == 0x8100 {
3172 if innerEthType == 0x8100 {
3173 // q-in-q 802.1ad or 802.1q double tagged packet.
3174 // get the inner vlanId
3175 index = 18
3176 } else {
3177 index = 14
3178 }
3179 priority := (packet[index] >> 5) & 0x7
3180 //13 bits composes vlanId value
3181 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3182 return vlan, priority, nil
3183 }
3184 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3185 return 0, 0, nil
3186}
3187
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303188// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303189func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003190
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003191 f.onuGemInfoLock.Lock()
3192 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003193
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003194 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303195 for idx, onu := range onugem {
3196 if onu.OnuID == onuID {
3197 for _, uni := range onu.UniPorts {
3198 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199 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 +05303200 return
3201 }
3202 }
3203 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003204 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303205 }
3206 }
npujarec5762e2020-01-01 14:08:48 +05303207 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003208
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303209}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303210
npujarec5762e2020-01-01 14:08:48 +05303211func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3212 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303213 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303215 return
3216 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303218 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003219 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303220 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003221 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303222}
Esin Karamanccb714b2019-11-29 15:02:06 +00003223
Girish Gowdra9602eb42020-09-09 15:50:39 -07003224//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3225// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003226func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003227 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003228 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003229 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3230 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3231
Esin Karamanccb714b2019-11-29 15:02:06 +00003232 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003233 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 -07003234 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003235 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003236
3237 var onuID = int32(NoneOnuID)
3238 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003239 var flowID uint64
3240 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3241 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3242 log.Fields{
3243 "flow": flow,
3244 "device-id": f.deviceHandler.device.Id,
3245 "intf-id": networkInterfaceID,
3246 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003247 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003248 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3249 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3250 log.Fields{
3251 "flow": flowInfo.Flow,
3252 "flow-id": flow.Id,
3253 "device-id": f.deviceHandler.device.Id})
3254 // Remove from device
3255 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3256 // DKB
3257 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3258 log.Fields{
3259 "flow-id": flow.Id,
3260 "error": err})
3261 return err
3262 }
3263 // Remove flow from KV store
3264 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flowID)
Esin Karamanccb714b2019-11-29 15:02:06 +00003265}
3266
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003267// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3268func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3269 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3270 if err != nil {
3271 _ = olterrors.NewErrNotFound("onu", log.Fields{
3272 "pon-port": f.ponPortIdx}, err).Log()
3273 return
3274 }
3275
3276 f.subscriberDataPathFlowIDMapLock.Lock()
3277 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3278
3279 for _, onu := range onuGemInfo {
3280 for _, uniID := range onu.UniPorts {
3281 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3282 if err != nil {
3283 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3284 }
3285 for _, flowID := range flowIDs {
3286 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3287 if flowInfo == nil {
3288 // Error is already logged in the called function
3289 continue
3290 }
3291 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3292 flowInfo.Flow.FlowType == Downstream &&
3293 flowInfo.Flow.Classifier.OVid > 0 &&
3294 flowInfo.Flow.TechProfileId > 0 {
3295 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3296 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3297 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3298 }
3299 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3300 flowInfo.Flow.FlowType == Upstream &&
3301 flowInfo.Flow.Action.OVid > 0 &&
3302 flowInfo.Flow.TechProfileId > 0 {
3303 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3304 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3305 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3306 }
3307 }
3308 }
3309 }
3310 }
3311}
3312
3313// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3314func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3315 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3316}