blob: 618a3f42378a28386d91e6b7d810af0b47c2ee8c [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"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000138 //GemID constant
139 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000140
141 //NoneOnuID constant
142 NoneOnuID = -1
143 //NoneUniID constant
144 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700145
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700146 // Max number of flows that can be queued per ONU
147 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530148
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700149 bitMapPrefix = "0b"
150 pbit1 = '1'
151)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400152
Esin Karamandf392e12020-12-16 13:33:09 +0000153type gemPortKey struct {
154 intfID uint32
155 gemPort uint32
156}
157
Gamze Abakafee36392019-10-03 11:17:24 +0000158type schedQueue struct {
159 direction tp_pb.Direction
160 intfID uint32
161 onuID uint32
162 uniID uint32
163 tpID uint32
164 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700165 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000166 meterID uint32
167 flowMetadata *voltha.FlowMetadata
168}
169
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700170// subscriberDataPathFlowIDKey is key to subscriberDataPathFlowIDMap map
171type subscriberDataPathFlowIDKey struct {
172 intfID uint32
173 onuID uint32
174 uniID uint32
175 direction string
176 tpID uint32
177}
178
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700179// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
180// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
181// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
182// flow and processes it serially
183type flowControlBlock struct {
184 ctx context.Context // Flow handler context
185 addFlow bool // if true flow to be added, else removed
186 flow *voltha.OfpFlowStats // Flow message
187 flowMetadata *voltha.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
188 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000189}
190
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700191//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530192type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700193 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
194 techprofile map[uint32]tp.TechProfileIf
195 deviceHandler *DeviceHandler
196 grpMgr *OpenOltGroupMgr
197 resourceMgr *rsrcMgr.OpenOltResourceMgr
198
199 onuIdsLock sync.RWMutex // TODO: Do we need this?
200
201 flowsUsedByGemPort map[uint32][]uint64 // gem port id to flow ids
202 flowsUsedByGemPortKey sync.RWMutex // lock to be used to access the flowsUsedByGemPort map
203
204 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
205 packetInGemPortLock sync.RWMutex
206
Matteo Scandolo2c0d2742020-06-10 11:28:42 -0700207 // TODO create a type rsrcMgr.OnuGemInfos to be used instead of []rsrcMgr.OnuGemInfo
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700208 onuGemInfo []rsrcMgr.OnuGemInfo //onu, gem and uni info local cache
Matteo Scandoloabf9c512020-06-23 19:31:14 -0700209 // We need to have a global lock on the onuGemInfo map
Girish Gowdra9602eb42020-09-09 15:50:39 -0700210 onuGemInfoLock sync.RWMutex
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700211
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700212 // Map of voltha flowID associated with subscriberDataPathFlowIDKey
213 // This information is not persisted on Kv store and hence should be reconciled on adapter restart
214 subscriberDataPathFlowIDMap map[subscriberDataPathFlowIDKey]uint64
215 subscriberDataPathFlowIDMapLock sync.RWMutex
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700216
217 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
218 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
219 incomingFlows []chan flowControlBlock
Esin Karamandf392e12020-12-16 13:33:09 +0000220
221 //this map keeps uni port info by gem and pon port. This relation shall be used for packet-out operations
222 gemToUniMap map[gemPortKey][]uint32
223 //We need to have a global lock on the gemToUniLock map
224 gemToUniLock sync.RWMutex
manikkaraj kbf256be2019-03-25 00:13:48 +0530225}
226
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700227//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700228func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000229 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530230 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 var err error
232 var idx uint32
233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra9602eb42020-09-09 15:50:39 -0700235 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.resourceMgr = rMgr
Amit Ghoshd4cbe482019-11-21 12:07:14 +0000237 flowMgr.techprofile = make(map[uint32]tp.TechProfileIf)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000238 if err = flowMgr.populateTechProfilePerPonPort(ctx); err != nil {
239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"error": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530240 return nil
241 }
William Kurkian740a09c2019-10-23 17:07:38 -0400242 flowMgr.onuIdsLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700243 flowMgr.flowsUsedByGemPort = make(map[uint32][]uint64)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530244 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700245 flowMgr.packetInGemPortLock = sync.RWMutex{}
Girish Gowdra1183b4d2020-08-25 16:12:01 -0700246 flowMgr.onuGemInfoLock = sync.RWMutex{}
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700247 flowMgr.subscriberDataPathFlowIDMap = make(map[subscriberDataPathFlowIDKey]uint64)
248 flowMgr.subscriberDataPathFlowIDMapLock = sync.RWMutex{}
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700249
250 // Create a slice of buffered channels for handling concurrent flows per ONU.
251 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
252 flowMgr.incomingFlows = make([]chan flowControlBlock, MaxOnusPerPon+1)
253 for i := range flowMgr.incomingFlows {
254 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
255 // Spin up a go routine to handling incoming flows (add/remove).
256 // There will be on go routine per ONU.
257 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
258 go flowMgr.perOnuFlowHandlerRoutine(flowMgr.incomingFlows[i])
259 }
260
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530261 //Load the onugem info cache from kv store on flowmanager start
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 if flowMgr.onuGemInfo, err = rMgr.GetOnuGemInfo(ctx, ponPortIdx); err != nil {
263 logger.Error(ctx, "failed-to-load-onu-gem-info-cache")
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530264 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700265 //Load flowID list per gem map per interface from the kvstore.
266 flowMgr.loadFlowIDlistForGem(ctx, idx)
Esin Karamanccb714b2019-11-29 15:02:06 +0000267 //load interface to multicast queue map from kv store
Esin Karamandf392e12020-12-16 13:33:09 +0000268
269 flowMgr.gemToUniMap = make(map[gemPortKey][]uint32)
270 flowMgr.gemToUniLock = sync.RWMutex{}
271
Girish Gowdra9602eb42020-09-09 15:50:39 -0700272 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700273 flowMgr.reconcileSubscriberDataPathFlowIDMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000274 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530275 return &flowMgr
276}
277
Esin Karamandf392e12020-12-16 13:33:09 +0000278// toGemToUniMap adds uni info consisting of onu and uni ID to the map and associates it with a gem port
279func (f *OpenOltFlowMgr) toGemToUniMap(ctx context.Context, gemPK gemPortKey, onuID uint32, uniID uint32) {
280 f.gemToUniLock.Lock()
281 f.gemToUniMap[gemPK] = []uint32{onuID, uniID}
282 f.gemToUniLock.Unlock()
283}
284
285// fromGemToUniMap returns onu and uni ID associated with the given key
286func (f *OpenOltFlowMgr) fromGemToUniMap(key gemPortKey) ([]uint32, bool) {
287 f.gemToUniLock.RLock()
288 defer f.gemToUniLock.RUnlock()
289 val, ok := f.gemToUniMap[key]
290 return val, ok
291}
292
293// removeFromGemToUniMap removes an entry associated with the given key from gemToUniMap
294func (f *OpenOltFlowMgr) removeFromGemToUniMap(key gemPortKey) {
295 f.gemToUniLock.Lock()
296 defer f.gemToUniLock.Unlock()
297 delete(f.gemToUniMap, key)
298}
299
Kent Hagermane6ff1012020-07-14 15:07:53 -0400300func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700301 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
302 // Flow is not replicated in this case, we need to register the flow for a single gem-port
303 return f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
304 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
305 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
306 for _, gemPort := range deviceFlow.PbitToGemport {
307 if err := f.registerFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
308 return err
309 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700310 }
Gamze Abakafee36392019-10-03 11:17:24 +0000311 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700312 return nil
313}
314
315func (f *OpenOltFlowMgr) registerFlowIDForGem(ctx context.Context, accessIntfID uint32, gemPortID uint32, flowFromCore *ofp.OfpFlowStats) error {
316 f.flowsUsedByGemPortKey.Lock()
317 flowIDList, ok := f.flowsUsedByGemPort[gemPortID]
318 if !ok {
319 flowIDList = []uint64{flowFromCore.Id}
320 }
321 flowIDList = appendUnique64bit(flowIDList, flowFromCore.Id)
322 f.flowsUsedByGemPort[gemPortID] = flowIDList
323 f.flowsUsedByGemPortKey.Unlock()
324
325 // update the flowids for a gem to the KVstore
326 return f.resourceMgr.UpdateFlowIDsForGem(ctx, accessIntfID, gemPortID, flowIDList)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -0400327}
328
Girish Gowdra9602eb42020-09-09 15:50:39 -0700329func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000330 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
Andrea Campanellabfe08432020-09-11 17:07:03 +0200331 UsMeterID uint32, DsMeterID uint32, flowMetadata *voltha.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000332 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530333 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700334 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530335
Neha Sharma96b7bf22020-06-15 10:37:32 +0000336 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530337 "device-id": f.deviceHandler.device.Id,
338 "intf-id": intfID,
339 "onu-id": onuID,
340 "uni-id": uniID,
341 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700342 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530343 "action": actionInfo,
344 "usmeter-iD": UsMeterID,
345 "dsmeter-iD": DsMeterID,
346 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400347 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
348 // is because the flow is an NNI flow and there would be no onu resources associated with it
349 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400350 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200351 cause := "no-onu-id-for-flow"
352 fields := log.Fields{
353 "onu": onuID,
354 "port-no": portNo,
355 "classifer": classifierInfo,
356 "action": actionInfo,
357 "device-id": f.deviceHandler.device.Id}
358 logger.Errorw(ctx, cause, fields)
359 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530360 }
361
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700362 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000363 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530364 "uni": uni,
365 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530366
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700367 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
368 "device-id": f.deviceHandler.device.Id,
369 "intf-id": intfID,
370 "onu-id": onuID,
371 "uni-id": uniID,
372 "port-no": portNo,
373 "classifier": classifierInfo,
374 "action": actionInfo,
375 "usmeter-id": UsMeterID,
376 "dsmeter-id": DsMeterID,
377 "tp-id": TpID})
378 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
379 if allocID == 0 || gemPorts == nil || TpInst == nil {
380 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
381 return olterrors.NewErrNotFound(
382 "alloc-id-gem-ports-tp-unavailable",
383 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400384 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700385 args := make(map[string]uint32)
386 args[IntfID] = intfID
387 args[OnuID] = onuID
388 args[UniID] = uniID
389 args[PortNo] = portNo
390 args[AllocID] = allocID
391
392 /* Flows can be added specific to gemport if p-bits are received.
393 * If no pbit mentioned then adding flows for all gemports
394 */
395 f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
396
Andrea Campanellabfe08432020-09-11 17:07:03 +0200397 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530398}
399
salmansiddiqui7ac62132019-08-22 03:58:50 +0000400// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530401func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402
Neha Sharma96b7bf22020-06-15 10:37:32 +0000403 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530404 log.Fields{"dir": sq.direction,
405 "intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "tp-id": sq.tpID,
409 "meter-id": sq.meterID,
410 "tp-inst": sq.tpInst,
411 "flowmetadata": sq.flowMetadata,
412 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413
Gamze Abakafee36392019-10-03 11:17:24 +0000414 Direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000415 if err != nil {
416 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400417 }
418
419 /* Lets make a simple assumption that if the meter-id is present on the KV store,
420 * then the scheduler and queues configuration is applied on the OLT device
421 * in the given direction.
422 */
salmansiddiqui7ac62132019-08-22 03:58:50 +0000423
Manikkaraj kb1d51442019-07-23 10:41:02 -0400424 var SchedCfg *tp_pb.SchedulerConfig
npujarec5762e2020-01-01 14:08:48 +0530425 KvStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400426 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530427 return olterrors.NewErrNotFound("meter",
428 log.Fields{"intf-id": sq.intfID,
429 "onu-id": sq.onuID,
430 "uni-id": sq.uniID,
431 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400432 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000433
Manikkaraj kb1d51442019-07-23 10:41:02 -0400434 if KvStoreMeter != nil {
Gamze Abakafee36392019-10-03 11:17:24 +0000435 if KvStoreMeter.MeterId == sq.meterID {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000436 logger.Debugw(ctx, "scheduler-already-created-for-upstream", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400437 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
Thomas Lee S94109f12020-03-03 16:39:29 +0530439 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800440 "unsupported": "meter-id",
441 "kv-store-meter-id": KvStoreMeter.MeterId,
Shrey Baid26912972020-04-16 21:02:31 +0530442 "meter-id-in-flow": sq.meterID,
443 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400444 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
Neha Sharma96b7bf22020-06-15 10:37:32 +0000446 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530447 log.Fields{
448 "meter-id": sq.meterID,
449 "direction": Direction,
450 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451
Gamze Abakafee36392019-10-03 11:17:24 +0000452 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Gamze Abakafee36392019-10-03 11:17:24 +0000454 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400456 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000457
458 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530459 return olterrors.NewErrNotFound("scheduler-config",
460 log.Fields{
461 "intf-id": sq.intfID,
462 "direction": sq.direction,
463 "tp-inst": sq.tpInst,
464 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000465 }
466
Manikkaraj kb1d51442019-07-23 10:41:02 -0400467 var meterConfig *ofp.OfpMeterConfig
Gamze Abakafee36392019-10-03 11:17:24 +0000468 if sq.flowMetadata != nil {
469 for _, meter := range sq.flowMetadata.Meters {
470 if sq.meterID == meter.MeterId {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 meterConfig = meter
Neha Sharma96b7bf22020-06-15 10:37:32 +0000472 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Shrey Baid26912972020-04-16 21:02:31 +0530473 log.Fields{"meterConfig": meterConfig,
474 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 break
476 }
477 }
478 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000479 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400480 }
481 if meterConfig == nil {
Thomas Lee S94109f12020-03-03 16:39:29 +0530482 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800483 "reason": "Could-not-get-meterbands-from-flowMetadata",
484 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530485 "meter-id": sq.meterID,
486 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400487 } else if len(meterConfig.Bands) < MaxMeterBand {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000488 logger.Errorw(ctx, "invalid-number-of-bands-in-meter",
Shrey Baid26912972020-04-16 21:02:31 +0530489 log.Fields{"Bands": meterConfig.Bands,
490 "meter-id": sq.meterID,
491 "device-id": f.deviceHandler.device.Id})
Thomas Lee S94109f12020-03-03 16:39:29 +0530492 return olterrors.NewErrInvalidValue(log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800493 "reason": "Invalid-number-of-bands-in-meter",
494 "meterband-count": len(meterConfig.Bands),
495 "metabands": meterConfig.Bands,
Shrey Baid26912972020-04-16 21:02:31 +0530496 "meter-id": sq.meterID,
497 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 }
499 cir := meterConfig.Bands[0].Rate
500 cbs := meterConfig.Bands[0].BurstSize
501 eir := meterConfig.Bands[1].Rate
502 ebs := meterConfig.Bands[1].BurstSize
503 pir := cir + eir
504 pbs := cbs + ebs
505 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
506
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700507 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000508 TrafficSched[0].TechProfileId = sq.tpID
Manikkaraj kb1d51442019-07-23 10:41:02 -0400509
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700510 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530511 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
512 log.Fields{"intf-id": sq.intfID,
513 "direction": sq.direction,
514 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400515 }
516
salmansiddiqui7ac62132019-08-22 03:58:50 +0000517 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400518 * store the meter id on the KV store, for further reference.
519 */
npujarec5762e2020-01-01 14:08:48 +0530520 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 +0530521 return olterrors.NewErrAdapter("failed-updating-meter-id",
522 log.Fields{"onu-id": sq.onuID,
523 "meter-id": sq.meterID,
524 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000526 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530527 log.Fields{"direction": Direction,
528 "Meter": meterConfig,
529 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400530 return nil
531}
532
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700533func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000534 trafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000535
536 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530537 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
538 log.Fields{"intf-id": sq.intfID,
539 "direction": sq.direction,
540 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000541 }
542
Neha Sharma96b7bf22020-06-15 10:37:32 +0000543 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530544 log.Fields{
545 "direction": sq.direction,
546 "TrafficScheds": TrafficSched,
547 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530548 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 IntfId: sq.intfID, OnuId: sq.onuID,
550 UniId: sq.uniID, PortNo: sq.uniPort,
551 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000552 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000553 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000554 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530555 "direction": sq.direction,
556 "traffic-queues": trafficQueues,
557 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000558
559 // On receiving the CreateTrafficQueues request, the driver should create corresponding
560 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000561 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530562 log.Fields{"direction": sq.direction,
563 "traffic-queues": trafficQueues,
564 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530565 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx,
Girish Kumar8f73fe02019-12-09 13:19:37 +0000566 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
567 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000568 TrafficQueues: trafficQueues,
569 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530570 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000571 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000572 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530573 "direction": sq.direction,
574 "traffic-queues": trafficQueues,
575 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000576
Esin Karamanccb714b2019-11-29 15:02:06 +0000577 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 multicastTrafficQueues := f.techprofile[sq.intfID].GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile))
Esin Karamanccb714b2019-11-29 15:02:06 +0000579 if len(multicastTrafficQueues) > 0 {
Girish Gowdra9602eb42020-09-09 15:50:39 -0700580 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present {
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 //assumed that there is only one queue per PON for the multicast service
582 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
583 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000584 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700586 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000587 gemPortID: multicastQueuePerPonPort.GemportId,
588 servicePriority: multicastQueuePerPonPort.Priority,
589 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700590 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000591 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400592 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
593 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"error": err})
594 return err
595 }
Shrey Baid26912972020-04-16 21:02:31 +0530596
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000598 }
599 }
600 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000601 return nil
602}
603
salmansiddiqui7ac62132019-08-22 03:58:50 +0000604// RemoveSchedulerQueues removes the traffic schedulers from the device based on the given scheduler configuration and traffic shaping info
npujarec5762e2020-01-01 14:08:48 +0530605func (f *OpenOltFlowMgr) RemoveSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400606
607 var Direction string
608 var SchedCfg *tp_pb.SchedulerConfig
609 var err error
Neha Sharma96b7bf22020-06-15 10:37:32 +0000610 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530611 log.Fields{
612 "direction": sq.direction,
613 "intf-id": sq.intfID,
614 "onu-id": sq.onuID,
615 "uni-id": sq.uniID,
616 "uni-port": sq.uniPort,
617 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000618 if sq.direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000619 SchedCfg, err = f.techprofile[sq.intfID].GetUsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400620 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000621 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000622 SchedCfg, err = f.techprofile[sq.intfID].GetDsScheduler(ctx, sq.tpInst.(*tp.TechProfile))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400623 Direction = "downstream"
624 }
625
Girish Kumar8f73fe02019-12-09 13:19:37 +0000626 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530627 return olterrors.NewErrNotFound("scheduler-config",
628 log.Fields{
629 "int-id": sq.intfID,
630 "direction": sq.direction,
631 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000632 }
633
npujarec5762e2020-01-01 14:08:48 +0530634 KVStoreMeter, err := f.resourceMgr.GetMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400635 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530636 return olterrors.NewErrNotFound("meter",
637 log.Fields{
638 "onu-id": sq.onuID,
639 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400640 }
641 if KVStoreMeter == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000642 logger.Warnw(ctx, "no-meter-installed-yet",
Shrey Baid26912972020-04-16 21:02:31 +0530643 log.Fields{
644 "direction": Direction,
645 "intf-id": sq.intfID,
646 "onu-id": sq.onuID,
647 "uni-id": sq.uniID,
648 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400649 return nil
650 }
651 cir := KVStoreMeter.Bands[0].Rate
652 cbs := KVStoreMeter.Bands[0].BurstSize
653 eir := KVStoreMeter.Bands[1].Rate
654 ebs := KVStoreMeter.Bands[1].BurstSize
655 pir := cir + eir
656 pbs := cbs + ebs
657
658 TrafficShaping := &tp_pb.TrafficShapingInfo{Cir: cir, Cbs: cbs, Pir: pir, Pbs: pbs}
659
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700660 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile[sq.intfID].GetTrafficScheduler(sq.tpInst.(*tp.TechProfile), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000661 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000662
Neha Sharma96b7bf22020-06-15 10:37:32 +0000663 TrafficQueues, err := f.techprofile[sq.intfID].GetTrafficQueues(ctx, sq.tpInst.(*tp.TechProfile), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530665 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
666 log.Fields{
667 "intf-id": sq.intfID,
668 "direction": sq.direction,
669 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000670 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400671
npujarec5762e2020-01-01 14:08:48 +0530672 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
Gamze Abakafee36392019-10-03 11:17:24 +0000673 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
674 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000675 TrafficQueues: TrafficQueues,
676 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000677 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530678 log.Fields{
679 "intf-id": sq.intfID,
680 "traffic-queues": TrafficQueues,
681 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000683 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530684 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
Gamze Abakafee36392019-10-03 11:17:24 +0000685 IntfId: sq.intfID, OnuId: sq.onuID,
686 UniId: sq.uniID, PortNo: sq.uniPort,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 TrafficScheds: TrafficSched}); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +0000688 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530689 log.Fields{
690 "intf-id": sq.intfID,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700691 "traffic-schedulers": TrafficSched,
692 "onu-id": sq.onuID,
693 "uni-id": sq.uniID,
694 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400695 }
696
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700697 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
698 log.Fields{"device-id": f.deviceHandler.device.Id,
699 "intf-id": sq.intfID,
700 "onu-id": sq.onuID,
701 "uni-id": sq.uniID,
702 "uni-port": sq.uniPort})
salmansiddiqui7ac62132019-08-22 03:58:50 +0000703
704 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 * delete the meter id on the KV store.
706 */
npujarec5762e2020-01-01 14:08:48 +0530707 err = f.resourceMgr.RemoveMeterIDForOnu(ctx, Direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400708 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530709 return olterrors.NewErrAdapter("unable-to-remove-meter",
710 log.Fields{
711 "onu": sq.onuID,
712 "meter": KVStoreMeter.MeterId,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700713 "device-id": f.deviceHandler.device.Id,
714 "intf-id": sq.intfID,
715 "onu-id": sq.onuID,
716 "uni-id": sq.uniID,
717 "uni-port": sq.uniPort}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400718 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000719 logger.Infow(ctx, "removed-meter-from-KV-store-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530720 log.Fields{
721 "meter-id": KVStoreMeter.MeterId,
722 "dir": Direction,
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700723 "device-id": f.deviceHandler.device.Id,
724 "intf-id": sq.intfID,
725 "onu-id": sq.onuID,
726 "uni-id": sq.uniID,
727 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400728 return err
729}
730
Gamze Abakafee36392019-10-03 11:17:24 +0000731// This function allocates tconts and GEM ports for an ONU
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700732func (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 +0000733 var allocIDs []uint32
734 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530735 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530736 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000737 var err error
Gamze Abakafee36392019-10-03 11:17:24 +0000738
npujarec5762e2020-01-01 14:08:48 +0530739 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
740 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000741 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530742
Neha Sharma96b7bf22020-06-15 10:37:32 +0000743 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530744 "intf-id": intfID,
745 "onu-id": onuID,
746 "uni-id": uniID,
747 "device-id": f.deviceHandler.device.Id,
748 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530749
Manikkaraj kb1d51442019-07-23 10:41:02 -0400750 // Check tech profile instance already exists for derived port name
npujarec5762e2020-01-01 14:08:48 +0530751 techProfileInstance, _ := f.techprofile[intfID].GetTPInstanceFromKVStore(ctx, TpID, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000752 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000753 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530754 log.Fields{
755 "path": tpPath,
756 "device-id": f.deviceHandler.device.Id})
npujarec5762e2020-01-01 14:08:48 +0530757 techProfileInstance, err = f.techprofile[intfID].CreateTechProfInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000758 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530759 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000760 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530761 log.Fields{
762 "error": err,
763 "tp-id": TpID,
764 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000765 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530766 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400767 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
768 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"error": err})
769 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530770 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000771 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530772 log.Fields{
773 "uni": uni,
774 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530775 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530776 }
Gamze Abakafee36392019-10-03 11:17:24 +0000777
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700778 switch tpInst := techProfileInstance.(type) {
779 case *tp.TechProfile:
780 if UsMeterID != 0 {
781 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
782 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
783 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000784 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700785 log.Fields{
786 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700787 "onu-id": onuID,
788 "uni-id": uniID,
789 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700790 "meter-id": UsMeterID,
791 "device-id": f.deviceHandler.device.Id})
792 return 0, nil, nil
793 }
794 }
795 if DsMeterID != 0 {
796 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
797 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
798 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700800 log.Fields{
801 "error": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700802 "onu-id": onuID,
803 "uni-id": uniID,
804 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700805 "meter-id": DsMeterID,
806 "device-id": f.deviceHandler.device.Id})
807 return 0, nil, nil
808 }
809 }
810 allocID := tpInst.UsScheduler.AllocID
811 for _, gem := range tpInst.UpstreamGemPortAttributeList {
812 gemPortIDs = append(gemPortIDs, gem.GemportID)
813 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700814 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000815
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700816 if tpInstanceExists {
817 return allocID, gemPortIDs, techProfileInstance
818 }
819
820 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700821 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700822 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000823 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700824 log.Fields{
825 "alloc-ids": allocIDs,
826 "gemports": allgemPortIDs,
827 "device-id": f.deviceHandler.device.Id})
828 // Send Tconts and GEM ports to KV store
829 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530830 return allocID, gemPortIDs, techProfileInstance
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700831 case *tp.EponProfile:
832 // CreateSchedulerQueues for EPON needs to be implemented here
833 // when voltha-protos for EPON is completed.
834 allocID := tpInst.AllocID
835 for _, gem := range tpInst.UpstreamQueueAttributeList {
836 gemPortIDs = append(gemPortIDs, gem.GemportID)
837 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700838 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700839
840 if tpInstanceExists {
841 return allocID, gemPortIDs, techProfileInstance
842 }
843
844 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700845 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700848 log.Fields{
849 "alloc-ids": allocIDs,
850 "gemports": allgemPortIDs,
851 "device-id": f.deviceHandler.device.Id})
852 // Send Tconts and GEM ports to KV store
853 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
854 return allocID, gemPortIDs, techProfileInstance
855 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 log.Fields{
858 "tpInst": tpInst})
859 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530860 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530861}
862
npujarec5762e2020-01-01 14:08:48 +0530863func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530864
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530866 log.Fields{
867 "intf-id": intfID,
868 "onu-id": onuID,
869 "uni-id": uniID,
870 "alloc-id": allocID,
871 "gemport-ids": gemPortIDs,
872 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530873 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530874 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000875 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 +0530876 }
npujarec5762e2020-01-01 14:08:48 +0530877 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000878 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 +0530879 }
npujarec5762e2020-01-01 14:08:48 +0530880 if err := f.resourceMgr.UpdateGEMportsPonportToOnuMapOnKVStore(ctx, gemPortIDs, intfID, onuID, uniID); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Error(ctx, "error-while-uploading-gemtopon-map-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamandf392e12020-12-16 13:33:09 +0000882 } else {
883 //add to gem to uni cache
884 f.addGemPortUniAssociationsToCache(ctx, intfID, onuID, uniID, gemPortIDs)
manikkaraj kbf256be2019-03-25 00:13:48 +0530885 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000886 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 -0400887 for _, gemPort := range gemPortIDs {
npujarec5762e2020-01-01 14:08:48 +0530888 f.addGemPortToOnuInfoMap(ctx, intfID, onuID, gemPort)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400889 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530890}
891
Esin Karamandf392e12020-12-16 13:33:09 +0000892//addGemPortUniAssociationsToCache
893func (f *OpenOltFlowMgr) addGemPortUniAssociationsToCache(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortIDs []uint32) {
894 for _, gemPortID := range gemPortIDs {
895 key := gemPortKey{
896 intfID: intfID,
897 gemPort: gemPortID,
898 }
899 f.toGemToUniMap(ctx, key, onuID, uniID)
900 }
901 logger.Debugw(ctx, "gem-to-uni-info-added-to-cache", log.Fields{"device-id": f.deviceHandler.device.Id, "intfID": intfID,
902 "gemPortIDs": gemPortIDs, "onuID": onuID, "uniID": uniID})
903}
904
Neha Sharma96b7bf22020-06-15 10:37:32 +0000905func (f *OpenOltFlowMgr) populateTechProfilePerPonPort(ctx context.Context) error {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000906 var tpCount int
manikkaraj kbf256be2019-03-25 00:13:48 +0530907 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000908 for _, intfID := range techRange.IntfIds {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700909 f.techprofile[intfID] = f.resourceMgr.ResourceMgrs[intfID].TechProfileMgr
Manikkaraj kb1d51442019-07-23 10:41:02 -0400910 tpCount++
Neha Sharma96b7bf22020-06-15 10:37:32 +0000911 logger.Debugw(ctx, "init-tech-profile-done",
Shrey Baid26912972020-04-16 21:02:31 +0530912 log.Fields{
913 "intf-id": intfID,
914 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530915 }
916 }
917 //Make sure we have as many tech_profiles as there are pon ports on the device
Manikkaraj kb1d51442019-07-23 10:41:02 -0400918 if tpCount != int(f.resourceMgr.DevInfo.GetPonPorts()) {
Thomas Lee S94109f12020-03-03 16:39:29 +0530919 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530920 "reason": "tP-count-does-not-match-number-of-pon-ports",
David K. Bainbridge794735f2020-02-11 21:01:37 -0800921 "tech-profile-count": tpCount,
Shrey Baid26912972020-04-16 21:02:31 +0530922 "pon-port-count": f.resourceMgr.DevInfo.GetPonPorts(),
923 "device-id": f.deviceHandler.device.Id}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530924 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000925 logger.Infow(ctx, "populated-techprofile-for-ponports-successfully",
Shrey Baid26912972020-04-16 21:02:31 +0530926 log.Fields{
927 "numofTech": tpCount,
928 "numPonPorts": f.resourceMgr.DevInfo.GetPonPorts(),
929 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530930 return nil
931}
932
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700933func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530934 portNo uint32, uplinkClassifier map[string]interface{},
935 uplinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700936 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700937 uplinkClassifier[PacketTagType] = SingleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000938 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530939 log.Fields{
940 "uplinkClassifier": uplinkClassifier,
941 "uplinkAction": uplinkAction})
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700942 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, uplinkClassifier, uplinkAction,
943 Upstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
Manikkaraj k884c1242019-04-11 16:26:42 +0530944 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530945}
946
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700947func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32,
Manikkaraj k884c1242019-04-11 16:26:42 +0530948 portNo uint32, downlinkClassifier map[string]interface{},
949 downlinkAction map[string]interface{}, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700950 allocID uint32, gemportID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700951 downlinkClassifier[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +0000952 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530953 log.Fields{
954 "downlinkClassifier": downlinkClassifier,
955 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400956 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
957 if vlan, exists := downlinkClassifier[VlanVid]; exists {
958 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -0700959 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 if uint32(metadata.(uint64)) == MkUniPortNum(ctx, intfID, onuID, uniID) {
961 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +0530962 log.Fields{
963 "flow": logicalFlow,
964 "device-id": f.deviceHandler.device.Id,
965 "onu-id": onuID,
966 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -0800967 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -0400968 }
969 }
970 }
Manikkaraj k884c1242019-04-11 16:26:42 +0530971 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400972
Manikkaraj k884c1242019-04-11 16:26:42 +0530973 /* Already this info available classifier? */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700974 downlinkAction[PopVlan] = true
Matt Jeannereted16b7c2019-11-01 13:31:35 -0400975 // vlan_vid is a uint32. must be type asserted as such or conversion fails
976 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +0530977 if ok {
978 downlinkAction[VlanVid] = dlClVid & 0xfff
979 } else {
Thomas Lee S94109f12020-03-03 16:39:29 +0530980 return olterrors.NewErrInvalidValue(log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530981 "reason": "failed-to-convert-vlanid-classifier",
982 "vlan-id": VlanVid,
983 "device-id": f.deviceHandler.device.Id}, nil).Log()
Girish Gowdra26f344b2019-10-23 14:39:13 +0530984 }
985
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700986 return f.addSymmetricDataPathFlow(ctx, intfID, onuID, uniID, portNo, downlinkClassifier, downlinkAction,
987 Downstream, logicalFlow, allocID, gemportID, tpID, pbitToGem)
manikkaraj kbf256be2019-03-25 00:13:48 +0530988}
989
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700990func (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 +0530991 action map[string]interface{}, direction string, logicalFlow *ofp.OfpFlowStats,
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700992 allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
993
994 var inverseDirection string
995 if direction == Upstream {
996 inverseDirection = Downstream
997 } else {
998 inverseDirection = Upstream
999 }
1000
Neha Sharma96b7bf22020-06-15 10:37:32 +00001001 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301002 log.Fields{
1003 "intf-id": intfID,
1004 "onu-id": onuID,
1005 "uni-id": uniID,
1006 "device-id": f.deviceHandler.device.Id,
1007 "classifier": classifier,
1008 "action": action,
1009 "direction": direction,
1010 "alloc-id": allocID,
1011 "gemport-id": gemPortID,
1012 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001013
1014 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001015 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301016 log.Fields{
1017 "device-id": f.deviceHandler.device.Id,
1018 "intf-id": intfID,
1019 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001020 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301021 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001022 classifierProto, err := makeOpenOltClassifierField(classifier)
1023 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301024 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001026 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301027 log.Fields{
1028 "classifier": *classifierProto,
1029 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001030 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301032 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301033 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001034 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301035 log.Fields{
1036 "action": *actionProto,
1037 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301039 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301040 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001041 log.Fields{
1042 "classifier": classifier,
1043 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301044 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001045 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301046 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001047
1048 // Get symmetric flowID if it exists
1049 // This symmetric flowID will be needed by agent software to use the same device flow-id that was used for the
1050 // symmetric flow earlier
1051 // symmetric flowID 0 is considered by agent as non-existent symmetric flow
1052 keySymm := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: inverseDirection, tpID: tpID}
1053 f.subscriberDataPathFlowIDMapLock.RLock()
1054 symmFlowID := f.subscriberDataPathFlowIDMap[keySymm]
1055 f.subscriberDataPathFlowIDMapLock.RUnlock()
1056
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001057 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001058 OnuId: int32(onuID),
1059 UniId: int32(uniID),
1060 FlowId: logicalFlow.Id,
1061 FlowType: direction,
1062 AllocId: int32(allocID),
1063 NetworkIntfId: int32(networkIntfID),
1064 GemportId: int32(gemPortID),
1065 Classifier: classifierProto,
1066 Action: actionProto,
1067 Priority: int32(logicalFlow.Priority),
1068 Cookie: logicalFlow.Cookie,
1069 PortNo: portNo,
1070 TechProfileId: tpID,
1071 ReplicateFlow: len(pbitToGem) > 0,
1072 PbitToGemport: pbitToGem,
1073 SymmetricFlowId: symmFlowID,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001074 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001075 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001076 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301077 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001078 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301079 log.Fields{"direction": direction,
1080 "device-id": f.deviceHandler.device.Id,
1081 "flow": flow,
1082 "intf-id": intfID,
1083 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001084 flowInfo := rsrcMgr.FlowInfo{Flow: &flow, IsSymmtricFlow: true}
1085 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, uint32(flow.AccessIntfId), flow.OnuId, flow.UniId, flow.FlowId, flowInfo); err != nil {
1086 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301087 log.Fields{
1088 "flow": flow,
1089 "device-id": f.deviceHandler.device.Id,
1090 "intf-id": intfID,
1091 "onu-id": onuID}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001092 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001093
1094 // Update the current flowID to the map
1095 keyCurr := subscriberDataPathFlowIDKey{intfID: intfID, onuID: onuID, uniID: uniID, direction: direction, tpID: tpID}
1096 f.subscriberDataPathFlowIDMapLock.Lock()
1097 f.subscriberDataPathFlowIDMap[keyCurr] = logicalFlow.Id
1098 f.subscriberDataPathFlowIDMapLock.Unlock()
1099
David K. Bainbridge794735f2020-02-11 21:01:37 -08001100 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301101}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001102
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001103func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1104 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001105 gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301106
Neha Sharma96b7bf22020-06-15 10:37:32 +00001107 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301108 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301109 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001110 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301111 "action": action,
1112 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301114 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301115
1116 // Clear the action map
1117 for k := range action {
1118 delete(action, k)
1119 }
1120
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001121 action[TrapToHost] = true
1122 classifier[UDPSrc] = uint32(68)
1123 classifier[UDPDst] = uint32(67)
1124 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301125
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001126 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001127 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301128 log.Fields{
1129 "device-id": f.deviceHandler.device.Id,
1130 "intf-id": intfID,
1131 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301133 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301134
Neha Sharma96b7bf22020-06-15 10:37:32 +00001135 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301136 log.Fields{
1137 "ul_classifier": classifier,
1138 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001139 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301140 "intf-id": intfID,
1141 "onu-id": onuID,
1142 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301143
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 classifierProto, err := makeOpenOltClassifierField(classifier)
1145 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301146 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301147 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001148 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001149 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301151 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301152 }
1153
David K. Bainbridge794735f2020-02-11 21:01:37 -08001154 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001155 OnuId: int32(onuID),
1156 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001157 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001158 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 AllocId: int32(allocID),
1160 NetworkIntfId: int32(networkIntfID),
1161 GemportId: int32(gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162 Classifier: classifierProto,
1163 Action: actionProto,
1164 Priority: int32(logicalFlow.Priority),
1165 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001166 PortNo: portNo,
1167 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001168 ReplicateFlow: len(pbitToGem) > 0,
1169 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001170 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001172 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001174 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301175 log.Fields{
1176 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001177 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301178 "intf-id": intfID,
1179 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001180 flowInfo := rsrcMgr.FlowInfo{Flow: &dhcpFlow}
1181 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 +05301182 return olterrors.NewErrPersistence("update", "flow", dhcpFlow.FlowId,
1183 log.Fields{
1184 "flow": dhcpFlow,
1185 "device-id": f.deviceHandler.device.Id}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186 }
1187
David K. Bainbridge794735f2020-02-11 21:01:37 -08001188 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301189}
1190
Esin Karamanae41e2b2019-12-17 18:13:13 +00001191//addIGMPTrapFlow creates IGMP trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301192func (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 -07001193 action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32, gemPortID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
1194 return f.addUpstreamTrapFlow(ctx, intfID, onuID, uniID, portNo, classifier, action, logicalFlow, allocID, gemPortID, tpID, pbitToGem)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001195}
1196
1197//addUpstreamTrapFlow creates a trap-to-host flow
npujarec5762e2020-01-01 14:08:48 +05301198func (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 -07001199 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 +00001200
Neha Sharma96b7bf22020-06-15 10:37:32 +00001201 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001202 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301203 return olterrors.NewErrNotFound("nni-interface-id",
1204 log.Fields{
1205 "classifier": classifier,
1206 "action": action,
1207 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001209 }
1210
1211 // Clear the action map
1212 for k := range action {
1213 delete(action, k)
1214 }
1215
1216 action[TrapToHost] = true
1217 classifier[PacketTagType] = SingleTag
1218 delete(classifier, VlanVid)
1219
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001220 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001221 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001223 }
1224
Neha Sharma96b7bf22020-06-15 10:37:32 +00001225 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301226 log.Fields{
1227 "ul_classifier": classifier,
1228 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001229 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301230 "device-id": f.deviceHandler.device.Id,
1231 "intf-id": intfID,
1232 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001233
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 classifierProto, err := makeOpenOltClassifierField(classifier)
1235 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301236 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001238 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301239 log.Fields{
1240 "classifier": *classifierProto,
1241 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001242 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001243 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301244 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
David K. Bainbridge794735f2020-02-11 21:01:37 -08001247 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001248 OnuId: int32(onuID),
1249 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001250 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001251 FlowType: Upstream,
1252 AllocId: int32(allocID),
1253 NetworkIntfId: int32(networkIntfID),
1254 GemportId: int32(gemPortID),
1255 Classifier: classifierProto,
1256 Action: actionProto,
1257 Priority: int32(logicalFlow.Priority),
1258 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001259 PortNo: portNo,
1260 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001261 ReplicateFlow: len(pbitToGem) > 0,
1262 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001263 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001266 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 -08001267 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 flowInfo := rsrcMgr.FlowInfo{Flow: &flow}
1270 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 +05301271 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 +00001272 }
1273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001275}
1276
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001277// Add EAPOL flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001278func (f *OpenOltFlowMgr) addEAPOLFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
1279 classifier map[string]interface{}, action map[string]interface{}, logicalFlow *ofp.OfpFlowStats, allocID uint32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001280 gemPortID uint32, vlanID uint32, tpID uint32, pbitToGem map[uint32]uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Infow(ctx, "adding-eapol-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301282 log.Fields{
1283 "intf-id": intfID,
1284 "onu-id": onuID,
1285 "port-no": portNo,
1286 "alloc-id": allocID,
1287 "gemport-id": gemPortID,
1288 "vlan-id": vlanID,
1289 "flow": logicalFlow})
manikkaraj kbf256be2019-03-25 00:13:48 +05301290
1291 uplinkClassifier := make(map[string]interface{})
1292 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301293
manikkaraj kbf256be2019-03-25 00:13:48 +05301294 // Fill Classfier
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001295 uplinkClassifier[EthType] = uint32(EapEthType)
1296 uplinkClassifier[PacketTagType] = SingleTag
1297 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001298 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301299 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001300 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001301 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001302 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301303 "device-id": f.deviceHandler.device.Id,
1304 "onu-id": onuID,
1305 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301307 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301308 //Add Uplink EAPOL Flow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 logger.Debugw(ctx, "creating-ul-eapol-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301310 log.Fields{
1311 "ul_classifier": uplinkClassifier,
1312 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001313 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301314 "device-id": f.deviceHandler.device.Id,
1315 "intf-id": intfID,
1316 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301317
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1319 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301320 return olterrors.NewErrInvalidValue(log.Fields{
1321 "classifier": uplinkClassifier,
1322 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301323 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301325 log.Fields{
1326 "classifier": *classifierProto,
1327 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001328 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301330 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301331 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001332 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301333 log.Fields{
1334 "action": *actionProto,
1335 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001336 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301337 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301338 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301340 "action": action,
1341 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001342 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301343 }
1344
David K. Bainbridge794735f2020-02-11 21:01:37 -08001345 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001346 OnuId: int32(onuID),
1347 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001348 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001349 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001350 AllocId: int32(allocID),
1351 NetworkIntfId: int32(networkIntfID),
1352 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301353 Classifier: classifierProto,
1354 Action: actionProto,
1355 Priority: int32(logicalFlow.Priority),
1356 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001357 PortNo: portNo,
1358 TechProfileId: tpID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001359 ReplicateFlow: len(pbitToGem) > 0,
1360 PbitToGemport: pbitToGem,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001361 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001363 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001364 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001365 logger.Infow(ctx, "eapol-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301366 log.Fields{
1367 "device-id": f.deviceHandler.device.Id,
1368 "onu-id": onuID,
1369 "intf-id": intfID,
1370 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001371 flowInfo := rsrcMgr.FlowInfo{Flow: &upstreamFlow}
1372 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 +05301373 return olterrors.NewErrPersistence("update", "flow", upstreamFlow.FlowId,
1374 log.Fields{
1375 "flow": upstreamFlow,
1376 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301377 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001378 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301379}
1380
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001382 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001383
1384 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1385 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1386 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001387 if vlanID != ReservedVlan {
1388 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001389 classifier.OVid = vid
1390 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301391 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001392 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1393 vid := uint32(metadata)
1394 if vid != ReservedVlan {
Harsh Awasthiea45af72019-08-26 02:39:00 -04001395 classifier.IVid = vid
1396 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301397 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301398 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001399 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301400 classifier.OPbits = vlanPcp
1401 } else {
1402 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301403 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001404 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1405 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1406 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1407 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001408 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001409 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1410 classifier.PktTagType = pktTagType
1411
1412 switch pktTagType {
1413 case SingleTag:
1414 case DoubleTag:
1415 case Untagged:
1416 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001417 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301418 }
1419 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301421}
1422
Gamze Abaka724d0852020-03-18 12:10:24 +00001423func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001424 var actionCmd openoltpb2.ActionCmd
1425 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301426 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301428 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001429 if _, ok := actionInfo[VlanPcp]; ok {
1430 action.Cmd.RemarkInnerPbits = true
1431 action.IPbits = actionInfo[VlanPcp].(uint32)
1432 if _, ok := actionInfo[VlanVid]; ok {
1433 action.Cmd.TranslateInnerTag = true
1434 action.IVid = actionInfo[VlanVid].(uint32)
1435 }
1436 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001437 } else if _, ok := actionInfo[PushVlan]; ok {
1438 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301439 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001440 if _, ok := actionInfo[VlanPcp]; ok {
1441 action.OPbits = actionInfo[VlanPcp].(uint32)
1442 action.Cmd.RemarkOuterPbits = true
1443 if _, ok := classifierInfo[VlanVid]; ok {
1444 action.IVid = classifierInfo[VlanVid].(uint32)
1445 action.Cmd.TranslateInnerTag = true
1446 }
1447 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001448 } else if _, ok := actionInfo[TrapToHost]; ok {
1449 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301450 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00001451 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301452 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001453 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301454}
1455
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001456// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001457func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
1458 return f.techprofile[intfID].GetTechProfileInstanceKVPath(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301459}
1460
Gamze Abakafee36392019-10-03 11:17:24 +00001461// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001462func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301463 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001464 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1465
Gamze Abakafee36392019-10-03 11:17:24 +00001466 for _, tpID := range tpIDList {
npujarec5762e2020-01-01 14:08:48 +05301467 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04001468 _ = olterrors.NewErrAdapter("delete-tech-profile-failed", log.Fields{"device-id": f.deviceHandler.device.Id}, err).Log()
Girish Gowdra54934262019-11-13 14:19:55 +05301469 // return err
1470 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001471 }
Girish Kumara1ea2aa2020-08-19 18:14:22 +00001472 logger.Debugw(ctx, "tech-profile-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001473 }
1474 return nil
1475}
1476
1477// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301478func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001479 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001480 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001481 }
npujarec5762e2020-01-01 14:08:48 +05301482 if err := f.techprofile[intfID].DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301483 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1484 log.Fields{
1485 "tp-id": tpID,
1486 "uni-port-name": uniPortName,
1487 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001488 }
1489 return nil
1490}
1491
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001493
1494 var intfID uint32
1495 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1496 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1497 */
1498 if deviceFlow.AccessIntfId != -1 {
1499 intfID = uint32(deviceFlow.AccessIntfId)
1500 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001501 // We need to log the valid interface ID.
1502 // 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 +00001503 intfID = uint32(deviceFlow.NetworkIntfId)
1504 }
1505
Neha Sharma96b7bf22020-06-15 10:37:32 +00001506 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301507 "flow": *deviceFlow,
1508 "device-id": f.deviceHandler.device.Id,
1509 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001510 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001511
1512 st, _ := status.FromError(err)
1513 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001514 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001515 "err": err,
1516 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301517 "device-id": f.deviceHandler.device.Id,
1518 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001519 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301520 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001521
1522 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001523 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301524 log.Fields{"err": err,
1525 "device-flow": deviceFlow,
1526 "device-id": f.deviceHandler.device.Id,
1527 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001528 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001529 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001530 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301531 log.Fields{
1532 "flow": *deviceFlow,
1533 "device-id": f.deviceHandler.device.Id,
1534 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001535
1536 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1537 if deviceFlow.AccessIntfId != -1 {
1538 // No need to register the flow if it is a trap on nni flow.
1539 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1540 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1541 return err
1542 }
1543 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001544 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001545}
1546
Neha Sharma96b7bf22020-06-15 10:37:32 +00001547func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1548 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301549 log.Fields{
1550 "flow": *deviceFlow,
1551 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001552 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001553 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001554 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001555 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301556 log.Fields{
1557 "err": err,
1558 "deviceFlow": deviceFlow,
1559 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001560 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001561 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001562 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001563 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001564
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001565 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001566 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001567 "of-flow-id": ofFlowID,
1568 "flow": *deviceFlow,
1569 "device-id": f.deviceHandler.device.Id,
1570 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001571 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301572}
1573
David K. Bainbridge794735f2020-02-11 21:01:37 -08001574func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001575
1576 classifierInfo := make(map[string]interface{})
1577 actionInfo := make(map[string]interface{})
1578
1579 classifierInfo[EthType] = uint32(LldpEthType)
1580 classifierInfo[PacketTagType] = Untagged
1581 actionInfo[TrapToHost] = true
1582
1583 // LLDP flow is installed to trap LLDP packets on the NNI port.
1584 // We manage flow_id resource pool on per PON port basis.
1585 // Since this situation is tricky, as a hack, we pass the NNI port
1586 // index (network_intf_id) as PON port Index for the flow_id resource
1587 // pool. Also, there is no ONU Id available for trapping LLDP packets
1588 // on NNI port, use onu_id as -1 (invalid)
1589 // ****************** CAVEAT *******************
1590 // This logic works if the NNI Port Id falls within the same valid
1591 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1592 // we need to have a re-look at this.
1593 // *********************************************
1594
1595 var onuID = -1
1596 var uniID = -1
1597 var gemPortID = -1
1598
Neha Sharma96b7bf22020-06-15 10:37:32 +00001599 networkInterfaceID, err := IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301601 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001602 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001603 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001604 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001605 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001606 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001607
David K. Bainbridge794735f2020-02-11 21:01:37 -08001608 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1609 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301610 return olterrors.NewErrInvalidValue(
1611 log.Fields{
1612 "classifier": classifierInfo,
1613 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001614 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001615 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301616 log.Fields{
1617 "classifier": *classifierProto,
1618 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001619 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001620 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301621 return olterrors.NewErrInvalidValue(
1622 log.Fields{
1623 "action": actionInfo,
1624 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001625 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001626 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301627 log.Fields{
1628 "action": *actionProto,
1629 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001630
1631 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1632 OnuId: int32(onuID), // OnuId not required
1633 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001634 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001635 FlowType: Downstream,
1636 NetworkIntfId: int32(networkInterfaceID),
1637 GemportId: int32(gemPortID),
1638 Classifier: classifierProto,
1639 Action: actionProto,
1640 Priority: int32(flow.Priority),
1641 Cookie: flow.Cookie,
1642 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001643 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001644 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301645 log.Fields{
1646 "flow": downstreamflow,
1647 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001648 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001649 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301650 log.Fields{
1651 "device-id": f.deviceHandler.device.Id,
1652 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001653 "flow-id": flow.Id})
1654 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
1655 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
1656 return olterrors.NewErrPersistence("update", "flow", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301657 log.Fields{
1658 "flow": downstreamflow,
1659 "device-id": f.deviceHandler.device.Id}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001660 }
1661 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301662}
1663
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001664func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1665 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001666}
1667
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001668//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001670 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1671 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1672 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001673 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301674 log.Fields{
1675 "intf-id": intfID,
1676 "onu-id": onuID,
1677 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001679 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301680 return nil, olterrors.NewErrNotFound("onu-child-device",
1681 log.Fields{
1682 "onu-id": onuID,
1683 "intf-id": intfID,
1684 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001685 }
1686 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false)
1687 //better to ad the device to cache here.
1688 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1689 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001690 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301691 log.Fields{
1692 "intf-id": intfID,
1693 "onu-id": onuID,
1694 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001695 }
1696
1697 return onuDev.(*OnuDevice), nil
1698}
1699
1700//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001701func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1702 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301703 log.Fields{
1704 "pon-port": intfID,
1705 "onu-id": onuID,
1706 "device-id": f.deviceHandler.device.Id})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001707 parentPortNo := IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001709 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301710 return nil, olterrors.NewErrNotFound("onu",
1711 log.Fields{
1712 "interface-id": parentPortNo,
1713 "onu-id": onuID,
1714 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001715 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301716 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001717 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301718 log.Fields{
1719 "device-id": f.deviceHandler.device.Id,
1720 "child_device_id": onuDevice.Id,
1721 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301722 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301723}
1724
Neha Sharma96b7bf22020-06-15 10:37:32 +00001725func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1726 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301727 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001728 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301729 log.Fields{
1730 "intf-id": intfID,
1731 "onu-id": onuID,
1732 "uni-id": uniID,
1733 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001734 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301735 }
1736
1737 delGemPortMsg := &ic.InterAdapterDeleteGemPortMessage{UniId: uniID, TpPath: tpPath, GemPortId: gemPortID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001738 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301739 log.Fields{
1740 "msg": *delGemPortMsg,
1741 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001742 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301743 delGemPortMsg,
1744 ic.InterAdapterMessageType_DELETE_GEM_PORT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001745 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001746 onuDev.deviceType,
1747 onuDev.deviceID,
1748 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301749 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1750 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001751 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301752 "to-adapter": onuDev.deviceType,
1753 "onu-id": onuDev.deviceID,
1754 "proxyDeviceID": onuDev.proxyDeviceID,
1755 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301756 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001757 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301758 log.Fields{
1759 "msg": delGemPortMsg,
1760 "from-adapter": f.deviceHandler.device.Type,
1761 "to-adapter": onuDev.deviceType,
1762 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301763 return nil
1764}
1765
Neha Sharma96b7bf22020-06-15 10:37:32 +00001766func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1767 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301768 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
1771 "intf-id": intfID,
1772 "onu-id": onuID,
1773 "uni-id": uniID,
1774 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001775 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301776 }
1777
1778 delTcontMsg := &ic.InterAdapterDeleteTcontMessage{UniId: uniID, TpPath: tpPath, AllocId: allocID}
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301780 log.Fields{
1781 "msg": *delTcontMsg,
1782 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001783 if sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
Girish Gowdra6b130582019-11-20 16:45:20 +05301784 delTcontMsg,
1785 ic.InterAdapterMessageType_DELETE_TCONT_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03001786 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001787 onuDev.deviceType,
1788 onuDev.deviceID,
1789 onuDev.proxyDeviceID, ""); sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1791 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03001792 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05301793 "to-adapter": onuDev.deviceType, "onu-id": onuDev.deviceID,
1794 "proxyDeviceID": onuDev.proxyDeviceID,
1795 "device-id": f.deviceHandler.device.Id}, sendErr)
Girish Gowdra6b130582019-11-20 16:45:20 +05301796 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001797 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301798 log.Fields{
1799 "msg": delTcontMsg,
1800 "device-id": f.deviceHandler.device.Id})
Girish Gowdra6b130582019-11-20 16:45:20 +05301801 return nil
1802}
1803
Girish Gowdrac3037402020-01-22 20:29:53 +05301804// Once the gemport is released for a given onu, it also has to be cleared from local cache
1805// which was used for deriving the gemport->logicalPortNo during packet-in.
1806// Otherwise stale info continues to exist after gemport is freed and wrong logicalPortNo
1807// is conveyed to ONOS during packet-in OF message.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808func (f *OpenOltFlowMgr) deleteGemPortFromLocalCache(ctx context.Context, intfID uint32, onuID uint32, gemPortID uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001809
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001810 f.onuGemInfoLock.Lock()
1811 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07001812
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813 logger.Infow(ctx, "deleting-gem-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301814 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001815 "gem-port-id": gemPortID,
1816 "intf-id": intfID,
1817 "onu-id": onuID,
1818 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001819 "onu-gem": f.onuGemInfo})
Girish Gowdra9602eb42020-09-09 15:50:39 -07001820
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001821 onugem := f.onuGemInfo
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001822deleteLoop:
serkant.uluderya96af4932020-02-20 16:58:48 -08001823 for i, onu := range onugem {
Girish Gowdrac3037402020-01-22 20:29:53 +05301824 if onu.OnuID == onuID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001825 for j, gem := range onu.GemPorts {
Girish Gowdrac3037402020-01-22 20:29:53 +05301826 // If the gemport is found, delete it from local cache.
1827 if gem == gemPortID {
serkant.uluderya96af4932020-02-20 16:58:48 -08001828 onu.GemPorts = append(onu.GemPorts[:j], onu.GemPorts[j+1:]...)
1829 onugem[i] = onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Infow(ctx, "removed-gemport-from-local-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301831 log.Fields{
1832 "intf-id": intfID,
1833 "onu-id": onuID,
1834 "deletedgemport-id": gemPortID,
1835 "gemports": onu.GemPorts,
1836 "device-id": f.deviceHandler.device.Id})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001837 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301838 }
1839 }
Matteo Scandoloabf9c512020-06-23 19:31:14 -07001840 break deleteLoop
Girish Gowdrac3037402020-01-22 20:29:53 +05301841 }
1842 }
1843}
1844
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301845//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001846// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05301847func (f *OpenOltFlowMgr) clearResources(ctx context.Context, flow *ofp.OfpFlowStats, Intf uint32, onuID int32, uniID int32,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001848 gemPortID int32, flowID uint64, portNum uint32) error {
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001849
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001851 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301852 return olterrors.NewErrNotFound("tp-id",
1853 log.Fields{
1854 "flow": flow,
1855 "intf": Intf,
1856 "onu-id": onuID,
1857 "uni-id": uniID,
1858 "device-id": f.deviceHandler.device.Id}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05001859 }
Gamze Abakafee36392019-10-03 11:17:24 +00001860
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001861 uni := getUniPortPath(f.deviceHandler.device.Id, Intf, onuID, uniID)
1862 tpPath := f.getTPpath(ctx, Intf, uni, tpID)
1863 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1864 log.Fields{
1865 "tpPath": tpPath,
1866 "device-id": f.deviceHandler.device.Id})
1867 techprofileInst, err := f.techprofile[Intf].GetTPInstanceFromKVStore(ctx, tpID, tpPath)
1868 if err != nil || techprofileInst == nil { // This should not happen, something wrong in KV backend transaction
1869 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1870 log.Fields{
1871 "tp-id": tpID,
1872 "path": tpPath}, err)
1873 }
1874
1875 used := f.isGemPortUsedByAnotherFlow(uint32(gemPortID))
1876
1877 if used {
1878 f.flowsUsedByGemPortKey.Lock()
1879 defer f.flowsUsedByGemPortKey.Unlock()
1880
1881 flowIDs := f.flowsUsedByGemPort[uint32(gemPortID)]
1882 for i, flowIDinMap := range flowIDs {
1883 if flowIDinMap == flowID {
1884 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
1885 // everytime flowsUsedByGemPort cache is updated the same should be updated
1886 // in kv store by calling UpdateFlowIDsForGem
1887 f.flowsUsedByGemPort[uint32(gemPortID)] = flowIDs
1888 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, Intf, uint32(gemPortID), flowIDs); err != nil {
1889 return err
1890 }
1891 break
1892 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001893 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001894 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1895 log.Fields{
1896 "gemport-id": gemPortID,
1897 "usedByFlows": flowIDs,
1898 "device-id": f.deviceHandler.device.Id})
1899 return nil
1900 }
1901 logger.Debugf(ctx, "gem-port-id %d is-not-used-by-another-flow--releasing-the-gem-port", gemPortID)
1902 f.resourceMgr.RemoveGemPortIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1903 // TODO: The TrafficQueue corresponding to this gem-port also should be removed immediately.
1904 // But it is anyway eventually removed later when the TechProfile is freed, so not a big issue for now.
1905 f.resourceMgr.RemoveGEMportPonportToOnuMapOnKVStore(ctx, uint32(gemPortID), Intf)
Esin Karamandf392e12020-12-16 13:33:09 +00001906 // also clear gem to uni cache
1907 f.removeFromGemToUniMap(gemPortKey{
1908 intfID: Intf,
1909 gemPort: uint32(gemPortID),
1910 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001911 f.deleteGemPortFromLocalCache(ctx, Intf, uint32(onuID), uint32(gemPortID))
Esin Karamandf392e12020-12-16 13:33:09 +00001912
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001913 f.onuIdsLock.Lock() // TODO: What is this lock?
1914
1915 //everytime an entry is deleted from flowsUsedByGemPort cache, the same should be updated in kv as well
1916 // by calling DeleteFlowIDsForGem
1917 f.flowsUsedByGemPortKey.Lock()
1918 delete(f.flowsUsedByGemPort, uint32(gemPortID))
1919 f.flowsUsedByGemPortKey.Unlock()
1920 f.resourceMgr.DeleteFlowIDsForGem(ctx, Intf, uint32(gemPortID))
1921 f.resourceMgr.FreeGemPortID(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID))
1922
1923 f.onuIdsLock.Unlock()
1924
1925 // Delete the gem port on the ONU.
1926 if err := f.sendDeleteGemPortToChild(ctx, Intf, uint32(onuID), uint32(uniID), uint32(gemPortID), tpPath); err != nil {
1927 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
1928 log.Fields{
1929 "err": err,
1930 "intf": Intf,
1931 "onu-id": onuID,
1932 "uni-id": uniID,
1933 "device-id": f.deviceHandler.device.Id,
1934 "gemport-id": gemPortID})
1935 }
1936 switch techprofileInst := techprofileInst.(type) {
1937 case *tp.TechProfile:
1938 ok, _ := f.isTechProfileUsedByAnotherGem(ctx, Intf, uint32(onuID), uint32(uniID), tpID, techprofileInst, uint32(gemPortID))
1939 if !ok {
1940 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1941 logger.Warn(ctx, err)
1942 }
1943 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1944 logger.Warn(ctx, err)
1945 }
1946 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 {
1947 logger.Warn(ctx, err)
1948 }
1949 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 {
1950 logger.Warn(ctx, err)
1951 }
1952 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID)
1953 // Delete the TCONT on the ONU.
1954 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocID, tpPath); err != nil {
1955 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
1956 log.Fields{
1957 "intf": Intf,
1958 "onu-id": onuID,
1959 "uni-id": uniID,
1960 "device-id": f.deviceHandler.device.Id,
1961 "alloc-id": techprofileInst.UsScheduler.AllocID})
1962 }
1963 }
1964 case *tp.EponProfile:
1965 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, Intf, uint32(onuID), uint32(uniID), tpID); err != nil {
1966 logger.Warn(ctx, err)
1967 }
1968 if err := f.DeleteTechProfileInstance(ctx, Intf, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1969 logger.Warn(ctx, err)
1970 }
1971 f.resourceMgr.FreeAllocID(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID)
1972 // Delete the TCONT on the ONU.
1973 if err := f.sendDeleteTcontToChild(ctx, Intf, uint32(onuID), uint32(uniID), techprofileInst.AllocID, tpPath); err != nil {
1974 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05301975 log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001976 "intf": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05301977 "onu-id": onuID,
1978 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001979 "device-id": f.deviceHandler.device.Id,
1980 "alloc-id": techprofileInst.AllocID})
Gamze Abakafee36392019-10-03 11:17:24 +00001981 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001982 default:
1983 logger.Errorw(ctx, "error-unknown-tech",
1984 log.Fields{
1985 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001986 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001987
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301988 return nil
1989}
1990
David K. Bainbridge794735f2020-02-11 21:01:37 -08001991// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07001992func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001993 var flowInfo *rsrcMgr.FlowInfo
Neha Sharma96b7bf22020-06-15 10:37:32 +00001994 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05301995 log.Fields{
1996 "flowDirection": flowDirection,
1997 "flow": *flow,
1998 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00001999
2000 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002002 }
2003
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302004 classifierInfo := make(map[string]interface{})
2005
Neha Sharma96b7bf22020-06-15 10:37:32 +00002006 portNum, Intf, onu, uni, inPort, ethType, err := FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302007 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002008 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002009 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302010 }
Girish Gowdra3d633032019-12-10 16:37:05 +05302011
David K. Bainbridge794735f2020-02-11 21:01:37 -08002012 onuID := int32(onu)
2013 uniID := int32(uni)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302014
2015 for _, field := range flows.GetOfbFields(flow) {
2016 if field.Type == flows.IP_PROTO {
2017 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002018 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302019 }
2020 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002021 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302022 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002023 "flow-id": flow.Id,
2024 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302025 "onu-id": onuID,
2026 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302027
2028 if ethType == LldpEthType || ((classifierInfo[IPProto] == IPProtoDhcp) && (flowDirection == "downstream")) {
2029 onuID = -1
2030 uniID = -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002031 logger.Debug(ctx, "trap-on-nni-flow-set-oni--uni-to- -1")
2032 Intf, err = IntfIDFromNniPortNum(ctx, inPort)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002033 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002034 logger.Errorw(ctx, "invalid-in-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08002035 log.Fields{
2036 "port-number": inPort,
2037 "error": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038 return err
David K. Bainbridge794735f2020-02-11 21:01:37 -08002039 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302040 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002041 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); flowInfo == nil {
2042 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})
2043 return olterrors.NewErrPersistence("remove", "flow", flow.Id, log.Fields{"flow": flow}, err)
2044 }
2045 removeFlowMessage := openoltpb2.Flow{FlowId: flowInfo.Flow.FlowId, FlowType: flowInfo.Flow.FlowType}
2046 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flowInfo.Flow})
2047 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2048 return err
2049 }
2050 if err = f.resourceMgr.RemoveFlowIDInfo(ctx, Intf, onuID, uniID, flow.Id); err != nil {
2051 logger.Errorw(ctx, "failed-to-remove-flow-on-kv-store", log.Fields{"error": err})
2052 return err
2053 }
2054 if !flowInfo.Flow.ReplicateFlow {
2055 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, flowInfo.Flow.GemportId, flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002056 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002057 "flow-id": flow.Id,
2058 "stored-flow": flowInfo.Flow,
2059 "device-id": f.deviceHandler.device.Id,
2060 "stored-flow-id": flowInfo.Flow.FlowId,
2061 "onu-id": onuID,
2062 "intf": Intf,
2063 })
2064 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302065 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002066 } else {
2067 gems := make([]uint32, 0)
2068 for _, gem := range flowInfo.Flow.PbitToGemport {
2069 gems = appendUnique32bit(gems, gem)
2070 }
2071 logger.Debugw(ctx, "gems-to-be-cleared", log.Fields{"gems": gems})
2072 for _, gem := range gems {
2073 if err = f.clearResources(ctx, flow, Intf, onuID, uniID, int32(gem), flowInfo.Flow.FlowId, portNum); err != nil {
Girish Gowdra0aca4982021-01-04 12:44:27 -08002074 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002075 "flow-id": flow.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 "stored-flow": flowInfo.Flow,
Matteo Scandolo92186242020-06-12 10:54:18 -07002077 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002078 "stored-flow-id": flowInfo.Flow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07002079 "onu-id": onuID,
2080 "intf": Intf,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002081 "gem": gem,
Matteo Scandolo92186242020-06-12 10:54:18 -07002082 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002083 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302084 }
2085 }
2086 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002087
2088 // If datapath flow, clear the symmetric flow data from the subscriberDataPathFlowIDMap map
2089 if isDatapathFlow(flow) {
2090 if tpID, err := getTpIDFromFlow(ctx, flow); err != nil {
2091 var inverseDirection string
2092 if flowDirection == Upstream {
2093 inverseDirection = Downstream
2094 } else {
2095 inverseDirection = Upstream
2096 }
2097
2098 keySymm := subscriberDataPathFlowIDKey{intfID: Intf, onuID: uint32(onuID), uniID: uint32(uniID), direction: inverseDirection, tpID: tpID}
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002099 f.subscriberDataPathFlowIDMapLock.Lock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002100 delete(f.subscriberDataPathFlowIDMap, keySymm)
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002101 f.subscriberDataPathFlowIDMapLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002102 }
2103 }
2104 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002105}
2106
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002107//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002108func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002109
Neha Sharma96b7bf22020-06-15 10:37:32 +00002110 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302111 var direction string
2112 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002113
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302114 for _, action := range flows.GetActions(flow) {
2115 if action.Type == flows.OUTPUT {
2116 if out := action.GetOutput(); out != nil {
2117 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002118 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302119 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002120 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002121 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002122 }
2123 }
2124 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002125
2126 if flows.HasGroup(flow) {
2127 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002128 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Esin Karamanccb714b2019-11-29 15:02:06 +00002129 } else if IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302130 direction = Upstream
2131 } else {
2132 direction = Downstream
2133 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302134
Girish Gowdracefae192020-03-19 18:14:10 -07002135 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002136 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002137
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002138 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002139}
2140
Esin Karamanae41e2b2019-12-17 18:13:13 +00002141//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2142func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
2143 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
2144 if ethType, ok := classifierInfo[EthType]; ok {
2145 if ethType.(uint32) == IPv4EthType {
2146 if ipProto, ok := classifierInfo[IPProto]; ok {
2147 if ipProto.(uint32) == IgmpProto {
2148 return true
2149 }
2150 }
2151 }
2152 }
2153 }
2154 return false
2155}
2156
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002157// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
2158func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *voltha.OfpFlowStats, addFlow bool, flowMetadata *voltha.FlowMetadata) error {
2159 // Step1 : Fill flowControlBlock
2160 // Step2 : Push the flowControlBlock to ONU channel
2161 // Step3 : Wait on response channel for response
2162 // Step4 : Return error value
2163 logger.Debugw(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
2164 errChan := make(chan error)
2165 flowCb := flowControlBlock{
2166 ctx: ctx,
2167 addFlow: addFlow,
2168 flow: flow,
2169 flowMetadata: flowMetadata,
2170 errChan: &errChan,
2171 }
2172 inPort, outPort := getPorts(flow)
2173 var onuID uint32
2174 if inPort != InvalidPort && outPort != InvalidPort {
2175 _, _, onuID, _ = ExtractAccessFromFlow(inPort, outPort)
2176 }
2177 // inPort or outPort is InvalidPort for trap-from-nni flows.
2178 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2179 // Send the flowCb on the ONU flow channel
2180 f.incomingFlows[onuID] <- flowCb
2181 // Wait on the channel for flow handlers return value
2182 err := <-errChan
2183 logger.Debugw(ctx, "process-flow--received-resp", log.Fields{"flow": flow, "addFlow": addFlow, "err": err})
2184 return err
2185}
2186
2187// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2188// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
2189func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(subscriberFlowChannel chan flowControlBlock) {
2190 for {
2191 // block on the channel to receive an incoming flow
2192 // process the flow completely before proceeding to handle the next flow
2193 flowCb := <-subscriberFlowChannel
2194 if flowCb.addFlow {
2195 logger.Debugw(flowCb.ctx, "adding-flow",
2196 log.Fields{"device-id": f.deviceHandler.device.Id,
2197 "flowToAdd": flowCb.flow})
2198 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2199 // Pass the return value over the return channel
2200 *flowCb.errChan <- err
2201 } else {
2202 logger.Debugw(flowCb.ctx, "removing-flow",
2203 log.Fields{"device-id": f.deviceHandler.device.Id,
2204 "flowToRemove": flowCb.flow})
2205 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2206 // Pass the return value over the return channel
2207 *flowCb.errChan <- err
2208 }
2209 }
2210}
2211
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002212// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302213// nolint: gocyclo
Andrea Campanellac63bba92020-03-10 17:01:04 +01002214func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *voltha.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002215 classifierInfo := make(map[string]interface{})
2216 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002217 var UsMeterID uint32
2218 var DsMeterID uint32
2219
Neha Sharma96b7bf22020-06-15 10:37:32 +00002220 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302221 log.Fields{
2222 "flow": flow,
2223 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002224 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002225
Neha Sharma96b7bf22020-06-15 10:37:32 +00002226 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002227 if err != nil {
2228 // Error logging is already done in the called function
2229 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002230 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302231 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002232
Esin Karamanccb714b2019-11-29 15:02:06 +00002233 if flows.HasGroup(flow) {
2234 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002235 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002236 }
2237
manikkaraj k17652a72019-05-06 09:06:36 -04002238 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002239 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002240 if err != nil {
2241 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002242 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002243 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002244
Neha Sharma96b7bf22020-06-15 10:37:32 +00002245 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302246 log.Fields{
2247 "classifierinfo_inport": classifierInfo[InPort],
2248 "action_output": actionInfo[Output]})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002249 portNo, intfID, onuID, uniID := ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002250
Humera Kouser94d7a842019-08-25 19:04:32 -04002251 if ethType, ok := classifierInfo[EthType]; ok {
2252 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002253 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002254 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002255 }
2256 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002257 if ipProto, ok := classifierInfo[IPProto]; ok {
2258 if ipProto.(uint32) == IPProtoDhcp {
2259 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302260 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002261 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002262 return f.addDHCPTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002263 }
2264 }
2265 }
2266 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002267 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002268 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002269 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002270 }
A R Karthick1f85b802019-10-11 05:06:05 +00002271
npujarec5762e2020-01-01 14:08:48 +05302272 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002273
Neha Sharma96b7bf22020-06-15 10:37:32 +00002274 TpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302276 return olterrors.NewErrNotFound("tpid-for-flow",
2277 log.Fields{
2278 "flow": flow,
2279 "intf-id": IntfID,
2280 "onu-id": onuID,
2281 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002282 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002283 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302284 log.Fields{
2285 "tp-id": TpID,
2286 "intf-id": intfID,
2287 "onu-id": onuID,
2288 "uni-id": uniID})
David K. Bainbridge82efc492019-09-04 09:57:11 -07002289 if IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002290 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002291 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002292 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002293 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002295
2296 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002297 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002298}
Girish Gowdra3d633032019-12-10 16:37:05 +05302299
Esin Karamanccb714b2019-11-29 15:02:06 +00002300// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002301func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Esin Karamanccb714b2019-11-29 15:02:06 +00002302 classifierInfo[PacketTagType] = DoubleTag
Neha Sharma96b7bf22020-06-15 10:37:32 +00002303 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302304 "classifier-info": classifierInfo,
2305 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002306
Esin Karaman65409d82020-03-18 10:58:18 +00002307 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002308 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002309 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002310 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002311
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002312 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002313
David K. Bainbridge794735f2020-02-11 21:01:37 -08002314 onuID := NoneOnuID
2315 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002316
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002317 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002318 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002319 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002320 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002321 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2322 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002323 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002324 }
2325 groupID := actionInfo[GroupID].(uint32)
2326 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002327 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002328 FlowType: Multicast,
2329 NetworkIntfId: int32(networkInterfaceID),
2330 GroupId: groupID,
2331 Classifier: classifierProto,
2332 Priority: int32(flow.Priority),
2333 Cookie: flow.Cookie}
2334
Kent Hagermane6ff1012020-07-14 15:07:53 -04002335 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002336 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002337 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002339 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002340 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002341 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002342 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002343 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002344 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002345 //cached group can be removed now
2346 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
2347 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "error": err})
2348 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002349 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002350
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002351 flowInfo := rsrcMgr.FlowInfo{Flow: &multicastFlow}
2352 if err = f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id, flowInfo); err != nil {
2353 return olterrors.NewErrPersistence("update", "flow", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002354 }
2355 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002356}
2357
Esin Karaman65409d82020-03-18 10:58:18 +00002358//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2359func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2360 if inPort, ok := classifierInfo[InPort]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 nniInterfaceID, err := IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002362 if err != nil {
2363 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2364 }
2365 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002366 }
Esin Karaman65409d82020-03-18 10:58:18 +00002367 // find the first NNI interface id of the device
npujarec5762e2020-01-01 14:08:48 +05302368 nniPorts, e := f.resourceMgr.GetNNIFromKVStore(ctx)
Esin Karamanccb714b2019-11-29 15:02:06 +00002369 if e == nil && len(nniPorts) > 0 {
2370 return nniPorts[0], nil
2371 }
Thomas Lee S94109f12020-03-03 16:39:29 +05302372 return 0, olterrors.NewErrNotFound("nni-port", nil, e).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00002373}
2374
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002375//sendTPDownloadMsgToChild send payload
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002377
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302379 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302381 log.Fields{
2382 "intf-id": intfID,
2383 "onu-id": onuID,
2384 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002385 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302386 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002388
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002390 tpDownloadMsg := &ic.InterAdapterTechProfileDownloadMessage{UniId: uniID, Path: tpPath}
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Neha Sharma8f4e4322020-08-06 10:51:53 +00002392 sendErr := f.deviceHandler.AdapterProxy.SendInterAdapterMessage(log.WithSpanFromContext(context.Background(), ctx),
manikkaraj k17652a72019-05-06 09:06:36 -04002393 tpDownloadMsg,
2394 ic.InterAdapterMessageType_TECH_PROFILE_DOWNLOAD_REQUEST,
serkant.uluderya4aff1862020-09-17 23:35:26 +03002395 f.deviceHandler.openOLT.config.Topic,
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002396 onuDev.deviceType,
2397 onuDev.deviceID,
2398 onuDev.proxyDeviceID, "")
manikkaraj k17652a72019-05-06 09:06:36 -04002399 if sendErr != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302400 return olterrors.NewErrCommunication("send-techprofile-download-request",
2401 log.Fields{
serkant.uluderya4aff1862020-09-17 23:35:26 +03002402 "from-adapter": f.deviceHandler.openOLT.config.Topic,
Shrey Baid26912972020-04-16 21:02:31 +05302403 "to-adapter": onuDev.deviceType,
2404 "onu-id": onuDev.deviceID,
2405 "proxyDeviceID": onuDev.proxyDeviceID}, sendErr)
manikkaraj k17652a72019-05-06 09:06:36 -04002406 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002407 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302408 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302409}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002410
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302411//UpdateOnuInfo function adds onu info to cache and kvstore
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002412func (f *OpenOltFlowMgr) UpdateOnuInfo(ctx context.Context, intfID uint32, onuID uint32, serialNum string) error {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302413
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002414 f.onuGemInfoLock.Lock()
2415 defer f.onuGemInfoLock.Unlock()
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002416 onugem := f.onuGemInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07002417 // If the ONU already exists in onuGemInfo list, nothing to do
2418 for _, onu := range onugem {
2419 if onu.OnuID == onuID && onu.SerialNumber == serialNum {
2420 logger.Debugw(ctx, "onu-id-already-exists-in-cache",
2421 log.Fields{"onuID": onuID,
2422 "serialNum": serialNum})
2423 return nil
2424 }
2425 }
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002426
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302427 onu := rsrcMgr.OnuGemInfo{OnuID: onuID, SerialNumber: serialNum, IntfID: intfID}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002428 f.onuGemInfo = append(f.onuGemInfo, onu)
Chaitrashree G S1a55b882020-02-04 17:35:35 -05002429 if err := f.resourceMgr.AddOnuGemInfo(ctx, intfID, onu); err != nil {
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002430 return err
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302431 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Infow(ctx, "updated-onuinfo",
Shrey Baid26912972020-04-16 21:02:31 +05302433 log.Fields{
2434 "intf-id": intfID,
2435 "onu-id": onuID,
2436 "serial-num": serialNum,
2437 "onu": onu,
2438 "device-id": f.deviceHandler.device.Id})
Andrea Campanellab83b39d2020-03-30 11:41:16 +02002439 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002440}
2441
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302442//addGemPortToOnuInfoMap function adds GEMport to ONU map
npujarec5762e2020-01-01 14:08:48 +05302443func (f *OpenOltFlowMgr) addGemPortToOnuInfoMap(ctx context.Context, intfID uint32, onuID uint32, gemPort uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002444
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002445 f.onuGemInfoLock.Lock()
2446 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07002447
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Infow(ctx, "adding-gem-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302449 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002450 "gem-port-id": gemPort,
2451 "intf-id": intfID,
2452 "onu-id": onuID,
2453 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002454 "onu-gem": f.onuGemInfo})
2455 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302456 // update the gem to the local cache as well as to kv strore
2457 for idx, onu := range onugem {
2458 if onu.OnuID == onuID {
2459 // check if gem already exists , else update the cache and kvstore
2460 for _, gem := range onu.GemPorts {
2461 if gem == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "gem-already-in-cache-no-need-to-update-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05302463 log.Fields{
2464 "gem": gemPort,
2465 "device-id": f.deviceHandler.device.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302466 return
2467 }
2468 }
2469 onugem[idx].GemPorts = append(onugem[idx].GemPorts, gemPort)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002470 f.onuGemInfo = onugem
Girish Gowdra9602eb42020-09-09 15:50:39 -07002471 break
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302472 }
2473 }
npujarec5762e2020-01-01 14:08:48 +05302474 err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302475 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Errorw(ctx, "failed-to-add-gem-to-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302477 log.Fields{
2478 "intf-id": intfID,
2479 "onu-id": onuID,
2480 "gemPort": gemPort,
2481 "device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002482 return
2483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Infow(ctx, "gem-added-to-onu-info-map",
Shrey Baid26912972020-04-16 21:02:31 +05302485 log.Fields{
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002486 "gem-port-id": gemPort,
2487 "intf-id": intfID,
2488 "onu-id": onuID,
2489 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002490 "onu-gem": f.onuGemInfo})
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002491}
2492
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002493//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302494func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002495 var logicalPortNum uint32
Esin Karamandf392e12020-12-16 13:33:09 +00002496 var onuID, uniID uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002497 var err error
2498
2499 if packetIn.IntfType == "pon" {
2500 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002501 // get onu and uni ids associated with the given pon and gem ports
2502 if onuID, uniID, err = f.GetUniPortByPonPortGemPort(ctx, packetIn.IntfId, packetIn.GemportId); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002503 // Called method is returning error with all data populated; just return the same
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002504 return logicalPortNum, err
2505 }
Esin Karamandf392e12020-12-16 13:33:09 +00002506 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d")
2507
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002508 if packetIn.PortNo != 0 {
2509 logicalPortNum = packetIn.PortNo
2510 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logicalPortNum = MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002512 }
2513 // 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 +00002514 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002515 } else if packetIn.IntfType == "nni" {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002516 logicalPortNum = IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002517 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002518
2519 if logger.V(log.DebugLevel) {
2520 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2521 log.Fields{
2522 "logical-port-num": logicalPortNum,
2523 "intf-type": packetIn.IntfType,
2524 "packet": hex.EncodeToString(packetIn.Pkt),
2525 })
2526 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002527 return logicalPortNum, nil
2528}
2529
Esin Karamandf392e12020-12-16 13:33:09 +00002530//GetUniPortByPonPortGemPort return onu and uni IDs associated with given pon and gem ports
2531func (f *OpenOltFlowMgr) GetUniPortByPonPortGemPort(ctx context.Context, intfID uint32, gemPortID uint32) (uint32, uint32, error) {
2532 key := gemPortKey{
2533 intfID: intfID,
2534 gemPort: gemPortID,
2535 }
2536 uniPortInfo, ok := f.fromGemToUniMap(key) //try to get from the cache first
2537 if ok {
2538 if len(uniPortInfo) > 1 {
2539 //return onu ID and uni port from the cache
2540 logger.Debugw(ctx, "found-uni-port-by-pon-and-gem-ports",
2541 log.Fields{
2542 "intfID": intfID,
2543 "gemPortID": gemPortID,
2544 "onuID, uniID": uniPortInfo})
2545 return uniPortInfo[0], uniPortInfo[1], nil
2546 }
2547 }
2548 //If uni port is not found in cache try to get it from kv store. if it is found in kv store, update the cache and return.
2549 onuID, uniID, err := f.resourceMgr.GetUniPortByPonPortGemPortFromKVStore(ctx, intfID, gemPortID)
2550 if err == nil {
2551 f.toGemToUniMap(ctx, key, onuID, uniID)
2552 logger.Infow(ctx, "found-uni-port-by-pon-and-gem-port-from-kv-store-and-updating-cache-with-uni-port",
2553 log.Fields{
2554 "gemPortKey": key,
2555 "onuID": onuID,
2556 "uniID": uniID})
2557 return onuID, uniID, nil
2558 }
2559 return uint32(0), uint32(0), olterrors.NewErrNotFound("uni-id",
2560 log.Fields{"interfaceID": intfID, "gemPortID": gemPortID},
2561 errors.New("no uni port found"))
2562}
2563
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002564//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002565func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002566 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002567
2568 ctag, priority, err := getCTagFromPacket(ctx, packet)
2569 if err != nil {
2570 return 0, err
2571 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302572
Esin Karaman7fb80c22020-07-16 14:23:33 +00002573 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002574 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002575 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002576 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002577 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302578 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002579 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302580 log.Fields{
2581 "pktinkey": pktInkey,
2582 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002583
2584 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002585 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302586 //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 +00002587 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302588 if err == nil {
2589 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002590 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302591 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002592 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002593 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302594 log.Fields{
2595 "pktinkey": pktInkey,
2596 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302597 return gemPortID, nil
2598 }
2599 }
Shrey Baid26912972020-04-16 21:02:31 +05302600 return uint32(0), olterrors.NewErrNotFound("gem-port",
2601 log.Fields{
2602 "pktinkey": pktInkey,
2603 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002604
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002605}
2606
David K. Bainbridge794735f2020-02-11 21:01:37 -08002607func (f *OpenOltFlowMgr) addDHCPTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002608 logger.Debug(ctx, "adding-trap-dhcp-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002609 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002610 classifier[PacketTagType] = DoubleTag
2611 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002612 /* We manage flowId resource pool on per PON port basis.
2613 Since this situation is tricky, as a hack, we pass the NNI port
2614 index (network_intf_id) as PON port Index for the flowId resource
2615 pool. Also, there is no ONU Id available for trapping DHCP packets
2616 on NNI port, use onu_id as -1 (invalid)
2617 ****************** CAVEAT *******************
2618 This logic works if the NNI Port Id falls within the same valid
2619 range of PON Port Ids. If this doesn't work for some OLT Vendor
2620 we need to have a re-look at this.
2621 *********************************************
2622 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002623 onuID := -1
2624 uniID := -1
2625 gemPortID := -1
2626 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002627 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302628 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302629 return olterrors.NewErrNotFound("nni-intreface-id",
2630 log.Fields{
2631 "classifier": classifier,
2632 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002633 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302634 }
2635
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002636 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002638 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002639 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002640
David K. Bainbridge794735f2020-02-11 21:01:37 -08002641 classifierProto, err := makeOpenOltClassifierField(classifier)
2642 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002643 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002646 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002647 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002648 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002649 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002650 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002651 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2652 OnuId: int32(onuID), // OnuId not required
2653 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002654 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002655 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002656 AllocId: int32(allocID), // AllocId not used
2657 NetworkIntfId: int32(networkInterfaceID),
2658 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659 Classifier: classifierProto,
2660 Action: actionProto,
2661 Priority: int32(logicalFlow.Priority),
2662 Cookie: logicalFlow.Cookie,
2663 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002664 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002665 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002667 logger.Info(ctx, "dhcp-trap-on-nni-flow-added–to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002668 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2669 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2670 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002671 }
2672 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002674
Esin Karamanae41e2b2019-12-17 18:13:13 +00002675//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2676func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2677 var packetType string
2678 ovid, ivid := false, false
2679 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2680 vid := vlanID & VlanvIDMask
2681 if vid != ReservedVlan {
2682 ovid = true
2683 }
2684 }
2685 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2686 vid := uint32(metadata)
2687 if vid != ReservedVlan {
2688 ivid = true
2689 }
2690 }
2691 if ovid && ivid {
2692 packetType = DoubleTag
2693 } else if !ovid && !ivid {
2694 packetType = Untagged
2695 } else {
2696 packetType = SingleTag
2697 }
2698 return packetType
2699}
2700
2701//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002702func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002704 action := make(map[string]interface{})
2705 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2706 action[TrapToHost] = true
2707 /* We manage flowId resource pool on per PON port basis.
2708 Since this situation is tricky, as a hack, we pass the NNI port
2709 index (network_intf_id) as PON port Index for the flowId resource
2710 pool. Also, there is no ONU Id available for trapping packets
2711 on NNI port, use onu_id as -1 (invalid)
2712 ****************** CAVEAT *******************
2713 This logic works if the NNI Port Id falls within the same valid
2714 range of PON Port Ids. If this doesn't work for some OLT Vendor
2715 we need to have a re-look at this.
2716 *********************************************
2717 */
2718 onuID := -1
2719 uniID := -1
2720 gemPortID := -1
2721 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002722 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002723 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302724 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002725 "classifier": classifier,
2726 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002727 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002728 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002729 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002730 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002731 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002732 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002733
David K. Bainbridge794735f2020-02-11 21:01:37 -08002734 classifierProto, err := makeOpenOltClassifierField(classifier)
2735 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002736 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002737 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002738 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002739 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002740 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002741 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002742 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002743 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002744 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2745 OnuId: int32(onuID), // OnuId not required
2746 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002747 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 FlowType: Downstream,
2749 AllocId: int32(allocID), // AllocId not used
2750 NetworkIntfId: int32(networkInterfaceID),
2751 GemportId: int32(gemPortID), // GemportId not used
2752 Classifier: classifierProto,
2753 Action: actionProto,
2754 Priority: int32(logicalFlow.Priority),
2755 Cookie: logicalFlow.Cookie,
2756 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002757 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002758 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002761 flowInfo := rsrcMgr.FlowInfo{Flow: &downstreamflow}
2762 if err := f.resourceMgr.UpdateFlowIDInfo(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id, flowInfo); err != nil {
2763 return olterrors.NewErrPersistence("update", "flow", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002764 }
2765 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002766}
2767
salmansiddiqui7ac62132019-08-22 03:58:50 +00002768func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2769 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302770 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002771 }
2772 if Dir == tp_pb.Direction_UPSTREAM {
2773 return "upstream", nil
2774 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2775 return "downstream", nil
2776 }
2777 return "", nil
2778}
2779
Kent Hagermane6ff1012020-07-14 15:07:53 -04002780// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302781func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002782 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00002783 tpID uint32, uni string) {
Gamze Abakafee36392019-10-03 11:17:24 +00002784 var gemPort uint32
2785 intfID := args[IntfID]
2786 onuID := args[OnuID]
2787 uniID := args[UniID]
2788 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002789 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002790 pbitToGem := make(map[uint32]uint32)
2791
2792 if len(gemPorts) == 1 {
2793 // If there is only single gemport use that and do not populate pbitToGem map
2794 gemPort = gemPorts[0]
2795 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2796 for idx, gemID := range gemPorts {
2797 switch TpInst := TpInst.(type) {
2798 case *tp.TechProfile:
2799 pBitMap := TpInst.UpstreamGemPortAttributeList[idx].PbitMap
2800 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2801 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2802 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
2803 // this pcp bit traffic.
2804 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2805 if pbitSet == pbit1 {
2806 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2807 pbitToGem[pcp] = gemID
2808 }
2809 }
2810 default:
2811 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
2812 return
2813 }
2814 }
2815 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
2816 gemPort = f.techprofile[intfID].GetGemportIDForPbit(ctx, TpInst,
2817 tp_pb.Direction_UPSTREAM,
2818 pcp.(uint32))
2819 }
2820
salmansiddiqui7ac62132019-08-22 03:58:50 +00002821 if ipProto, ok := classifierInfo[IPProto]; ok {
2822 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002823 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002824 "tp-id": tpID,
2825 "alloc-id": allocID,
2826 "intf-id": intfID,
2827 "onu-id": onuID,
2828 "uni-id": uniID,
2829 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002830 //Adding DHCP upstream flow
2831 if err := f.addDHCPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2832 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002833 }
2834
Girish Gowdra32625212020-04-29 11:26:35 -07002835 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002836 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302837 log.Fields{
2838 "intf-id": intfID,
2839 "onu-id": onuID,
2840 "uni-id": uniID,
2841 "classifier-info:": classifierInfo})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002842 if err := f.addIGMPTrapFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2843 logger.Warn(ctx, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002844 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002845 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002846 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002847 return
2848 }
2849 } else if ethType, ok := classifierInfo[EthType]; ok {
2850 if ethType.(uint32) == EapEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002851 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002852 "intf-id": intfID,
2853 "onu-id": onuID,
2854 "uni-id": uniID,
2855 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 var vlanID uint32
2857 if val, ok := classifierInfo[VlanVid]; ok {
2858 vlanID = (val.(uint32)) & VlanvIDMask
2859 } else {
2860 vlanID = DefaultMgmtVlan
2861 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002862 if err := f.addEAPOLFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, vlanID, tpID, pbitToGem); err != nil {
2863 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002864 }
2865 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002866 } else if _, ok := actionInfo[PushVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002867 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002868 "intf-id": intfID,
2869 "onu-id": onuID,
2870 "uni-id": uniID,
2871 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002872 //Adding HSIA upstream flow
2873 if err := f.addUpstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2874 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002875 }
2876 } else if _, ok := actionInfo[PopVlan]; ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002877 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002878 "intf-id": intfID,
2879 "onu-id": onuID,
2880 "uni-id": uniID,
2881 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002882 //Adding HSIA downstream flow
2883 if err := f.addDownstreamDataPathFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, allocID, gemPort, tpID, pbitToGem); err != nil {
2884 logger.Warn(ctx, err)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002885 }
2886 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Errorw(ctx, "invalid-flow-type-to-handle",
Shrey Baid26912972020-04-16 21:02:31 +05302888 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002889 "intf-id": intfID,
2890 "onu-id": onuID,
2891 "uni-id": uniID,
Shrey Baid26912972020-04-16 21:02:31 +05302892 "classifier": classifierInfo,
2893 "action": actionInfo,
2894 "flow": flow})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002895 return
2896 }
2897 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002898 go func() {
2899 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID); err != nil {
2900 logger.Warn(ctx, err)
2901 }
2902 }()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903}
2904
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002905func (f *OpenOltFlowMgr) isGemPortUsedByAnotherFlow(gemPortID uint32) bool {
2906 f.flowsUsedByGemPortKey.RLock()
2907 flowIDList := f.flowsUsedByGemPort[gemPortID]
2908 f.flowsUsedByGemPortKey.RUnlock()
2909 return len(flowIDList) > 1
2910
Gamze Abakafee36392019-10-03 11:17:24 +00002911}
2912
npujarec5762e2020-01-01 14:08:48 +05302913func (f *OpenOltFlowMgr) isTechProfileUsedByAnotherGem(ctx context.Context, ponIntf uint32, onuID uint32, uniID uint32, tpID uint32, tpInst *tp.TechProfile, gemPortID uint32) (bool, uint32) {
2914 currentGemPorts := f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, ponIntf, onuID, uniID)
Gamze Abakafee36392019-10-03 11:17:24 +00002915 tpGemPorts := tpInst.UpstreamGemPortAttributeList
2916 for _, currentGemPort := range currentGemPorts {
2917 for _, tpGemPort := range tpGemPorts {
2918 if (currentGemPort == tpGemPort.GemportID) && (currentGemPort != gemPortID) {
2919 return true, currentGemPort
2920 }
2921 }
2922 }
Girish Gowdra54934262019-11-13 14:19:55 +05302923 if tpInst.InstanceCtrl.Onu == "single-instance" {
2924 // The TP information for the given TP ID, PON ID, ONU ID, UNI ID should be removed.
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002925 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, ponIntf, onuID, uniID, tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002926 logger.Warn(ctx, err)
2927 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002928 if err := f.DeleteTechProfileInstance(ctx, ponIntf, onuID, uniID, "", tpID); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002929 logger.Warn(ctx, err)
2930 }
Girish Gowdra54934262019-11-13 14:19:55 +05302931
2932 // Although we cleaned up TP Instance for the given (PON ID, ONU ID, UNI ID), the TP might
2933 // still be used on other uni ports.
2934 // So, we need to check and make sure that no other gem port is referring to the given TP ID
2935 // on any other uni port.
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002936 tpInstances := f.techprofile[ponIntf].FindAllTpInstances(ctx, tpID, ponIntf, onuID).([]tp.TechProfile)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002937 logger.Debugw(ctx, "got-single-instance-tp-instances", log.Fields{"tp-instances": tpInstances})
Girish Gowdra54934262019-11-13 14:19:55 +05302938 for i := 0; i < len(tpInstances); i++ {
2939 tpI := tpInstances[i]
2940 tpGemPorts := tpI.UpstreamGemPortAttributeList
Girish Gowdra6b130582019-11-20 16:45:20 +05302941 for _, tpGemPort := range tpGemPorts {
2942 if tpGemPort.GemportID != gemPortID {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Debugw(ctx, "single-instance-tp-is-in-use-by-gem", log.Fields{"gemPort": tpGemPort.GemportID})
Girish Gowdra6b130582019-11-20 16:45:20 +05302944 return true, tpGemPort.GemportID
Girish Gowdra54934262019-11-13 14:19:55 +05302945 }
2946 }
2947 }
2948 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Debug(ctx, "tech-profile-is-not-in-use-by-any-gem")
Gamze Abakafee36392019-10-03 11:17:24 +00002950 return false, 0
2951}
2952
Neha Sharma96b7bf22020-06-15 10:37:32 +00002953func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002954 for _, field := range flows.GetOfbFields(flow) {
2955 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002956 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002958 } else if field.Type == flows.ETH_DST {
2959 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002960 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002961 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002962 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002964 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002965 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002966 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002967 } else if field.Type == flows.VLAN_VID {
Girish Gowdra26f344b2019-10-23 14:39:13 +05302968 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00002969 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002970 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002972 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002973 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002975 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002976 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002977 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002978 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002979 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002981 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002982 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002984 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002985 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002986 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002987 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002988 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002989 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002990 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 return
2994 }
2995 }
2996}
2997
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002999 for _, action := range flows.GetActions(flow) {
3000 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003001 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003002 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003005 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 }
Scott Baker355d1742019-10-24 10:57:52 -07003007 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003008 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003010 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 if out := action.GetPush(); out != nil {
3012 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 } else {
3015 actionInfo[PushVlan] = true
3016 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003017 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303018 log.Fields{
3019 "push-tpid": actionInfo[TPID].(uint32),
3020 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 }
3022 }
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 if out := action.GetSetField(); out != nil {
3025 if field := out.GetField(); field != nil {
3026 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003027 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003028 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3030 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003031 }
3032 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003033 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003036 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 }
3038 }
3039 return nil
3040}
3041
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003043 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003044 fieldtype := ofbField.GetType()
3045 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003046 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3047 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003049 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003051 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003052 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3053 pcp := ofbField.GetVlanPcp()
3054 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003055 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003056 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003057 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003058 }
3059 }
3060}
3061
Neha Sharma96b7bf22020-06-15 10:37:32 +00003062func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003063 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003065 } else {
3066 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003068 }
3069}
3070
Neha Sharma96b7bf22020-06-15 10:37:32 +00003071func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003072 if isControllerFlow := IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003074 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
3075 if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003076 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303079 log.Fields{
3080 "newinport": classifierInfo[InPort].(uint32),
3081 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303083 return olterrors.NewErrNotFound("child-in-port",
3084 log.Fields{
3085 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3086 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 }
3088 }
3089 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003090 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003091 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
David K. Bainbridge82efc492019-09-04 09:57:11 -07003092 if portType := IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003093 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003094 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003095 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303096 log.Fields{
3097 "newoutport": actionInfo[Output].(uint32),
3098 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303100 return olterrors.NewErrNotFound("out-port",
3101 log.Fields{
3102 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3103 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 }
3105 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
3106 } else if portType := IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003107 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303110 log.Fields{
3111 "newinport": actionInfo[Output].(uint32),
3112 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003113 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303114 return olterrors.NewErrNotFound("nni-port",
3115 log.Fields{
3116 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3117 "in-port": classifierInfo[InPort].(uint32),
3118 "out-port": actionInfo[Output].(uint32),
3119 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003120 }
3121 }
3122 }
3123 return nil
3124}
Gamze Abakafee36392019-10-03 11:17:24 +00003125
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003127 /* Metadata 8 bytes:
3128 Most Significant 2 Bytes = Inner VLAN
3129 Next 2 Bytes = Tech Profile ID(TPID)
3130 Least Significant 4 Bytes = Port ID
3131 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3132 subscriber related flows.
3133 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003134 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003135 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003136 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003137 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003139 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003140}
3141
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003142func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3143 for _, sliceElement := range slice {
3144 if sliceElement == item {
3145 return slice
3146 }
3147 }
3148 return append(slice, item)
3149}
3150
3151func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003152 for _, sliceElement := range slice {
3153 if sliceElement == item {
3154 return slice
3155 }
3156 }
3157 return append(slice, item)
3158}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303159
3160// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003161func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303162
3163 portType := IntfIDToPortTypeName(classifier[InPort].(uint32))
3164 if portType == voltha.Port_PON_OLT {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165 intfID, err := IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003166 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003167 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003168 log.Fields{
3169 "port-number": action[Output].(uint32),
3170 "error": err})
3171 return uint32(0), err
3172 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303174 return intfID, nil
3175 } else if portType == voltha.Port_ETHERNET_NNI {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176 intfID, err := IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003177 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003179 log.Fields{
3180 "port-number": action[Output].(uint32),
3181 "error": err})
3182 return uint32(0), err
3183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303185 return intfID, nil
3186 }
3187 return uint32(0), nil
3188}
3189
3190// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003191func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3192 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3193 if err != nil {
3194 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3195 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3196 return
3197 }
3198 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003199
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003200 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003201 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003202 f.packetInGemPortLock.RUnlock()
3203
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303204 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003205 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003206 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 +05303207 log.Fields{
3208 "pktinkey": pktInkey,
3209 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003210 return
3211 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303212 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003213 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003214 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003215 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003216
npujarec5762e2020-01-01 14:08:48 +05303217 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 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 +05303219 log.Fields{
3220 "pktinkey": pktInkey,
3221 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303222}
3223
Esin Karaman7fb80c22020-07-16 14:23:33 +00003224//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3225func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3226 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003227 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003228 return 0, 0, errors.New("invalid packet length")
3229 }
3230 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3231 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3232
3233 var index int8
3234 if outerEthType == 0x8100 {
3235 if innerEthType == 0x8100 {
3236 // q-in-q 802.1ad or 802.1q double tagged packet.
3237 // get the inner vlanId
3238 index = 18
3239 } else {
3240 index = 14
3241 }
3242 priority := (packet[index] >> 5) & 0x7
3243 //13 bits composes vlanId value
3244 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3245 return vlan, priority, nil
3246 }
3247 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3248 return 0, 0, nil
3249}
3250
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303251// AddUniPortToOnuInfo adds uni port to the onugem info both in cache and kvstore.
npujarec5762e2020-01-01 14:08:48 +05303252func (f *OpenOltFlowMgr) AddUniPortToOnuInfo(ctx context.Context, intfID uint32, onuID uint32, portNum uint32) {
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003253
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003254 f.onuGemInfoLock.Lock()
3255 defer f.onuGemInfoLock.Unlock()
Matteo Scandolo2c0d2742020-06-10 11:28:42 -07003256
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003257 onugem := f.onuGemInfo
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303258 for idx, onu := range onugem {
3259 if onu.OnuID == onuID {
3260 for _, uni := range onu.UniPorts {
3261 if uni == portNum {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262 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 +05303263 return
3264 }
3265 }
3266 onugem[idx].UniPorts = append(onugem[idx].UniPorts, portNum)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003267 f.onuGemInfo = onugem
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303268 }
3269 }
npujarec5762e2020-01-01 14:08:48 +05303270 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNum)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003271
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303272}
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303273
npujarec5762e2020-01-01 14:08:48 +05303274func (f *OpenOltFlowMgr) loadFlowIDlistForGem(ctx context.Context, intf uint32) {
3275 flowIDsList, err := f.resourceMgr.GetFlowIDsGemMapForInterface(ctx, intf)
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303276 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003277 logger.Error(ctx, "failed-to-get-flowid-list-per-gem", log.Fields{"intf": intf})
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303278 return
3279 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003280 f.flowsUsedByGemPortKey.Lock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303281 for gem, FlowIDs := range flowIDsList {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003282 f.flowsUsedByGemPort[gem] = FlowIDs
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003284 f.flowsUsedByGemPortKey.Unlock()
Abhilash Laxmeshwar275c0742019-11-25 16:47:02 +05303285}
Esin Karamanccb714b2019-11-29 15:02:06 +00003286
Girish Gowdra9602eb42020-09-09 15:50:39 -07003287//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3288// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003289func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003290 classifierInfo := make(map[string]interface{})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003291 var flowInfo *rsrcMgr.FlowInfo
Girish Gowdra9602eb42020-09-09 15:50:39 -07003292 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
3293 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
3294
Esin Karamanccb714b2019-11-29 15:02:06 +00003295 if err != nil {
Girish Gowdra9602eb42020-09-09 15:50:39 -07003296 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 -07003297 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00003298 }
Girish Gowdra9602eb42020-09-09 15:50:39 -07003299
3300 var onuID = int32(NoneOnuID)
3301 var uniID = int32(NoneUniID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003302 if flowInfo = f.resourceMgr.GetFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id); flowInfo == nil {
3303 return olterrors.NewErrPersistence("remove", "flow", flow.Id,
3304 log.Fields{
3305 "flow": flow,
3306 "device-id": f.deviceHandler.device.Id,
3307 "intf-id": networkInterfaceID,
3308 "onu-id": onuID}, err).Log()
Esin Karamanccb714b2019-11-29 15:02:06 +00003309 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003310 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: flowInfo.Flow.FlowType}
3311 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3312 log.Fields{
3313 "flow": flowInfo.Flow,
3314 "flow-id": flow.Id,
3315 "device-id": f.deviceHandler.device.Id})
3316 // Remove from device
3317 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3318 // DKB
3319 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3320 log.Fields{
3321 "flow-id": flow.Id,
3322 "error": err})
3323 return err
3324 }
3325 // Remove flow from KV store
Girish Gowdra0aca4982021-01-04 12:44:27 -08003326 return f.resourceMgr.RemoveFlowIDInfo(ctx, networkInterfaceID, onuID, uniID, flow.Id)
Esin Karamanccb714b2019-11-29 15:02:06 +00003327}
3328
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003329// reconcileSubscriberDataPathFlowIDMap reconciles subscriberDataPathFlowIDMap from KV store
3330func (f *OpenOltFlowMgr) reconcileSubscriberDataPathFlowIDMap(ctx context.Context) {
3331 onuGemInfo, err := f.resourceMgr.GetOnuGemInfo(ctx, f.ponPortIdx)
3332 if err != nil {
3333 _ = olterrors.NewErrNotFound("onu", log.Fields{
3334 "pon-port": f.ponPortIdx}, err).Log()
3335 return
3336 }
3337
3338 f.subscriberDataPathFlowIDMapLock.Lock()
3339 defer f.subscriberDataPathFlowIDMapLock.Unlock()
3340
3341 for _, onu := range onuGemInfo {
3342 for _, uniID := range onu.UniPorts {
3343 flowIDs, err := f.resourceMgr.GetCurrentFlowIDsForOnu(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID))
3344 if err != nil {
3345 logger.Fatalf(ctx, "failed-to-read-flow-ids-of-onu-during-reconciliation")
3346 }
3347 for _, flowID := range flowIDs {
3348 flowInfo := f.resourceMgr.GetFlowIDInfo(ctx, onu.IntfID, int32(onu.OnuID), int32(uniID), flowID)
3349 if flowInfo == nil {
3350 // Error is already logged in the called function
3351 continue
3352 }
3353 if flowInfo.Flow.Classifier.PktTagType == DoubleTag &&
3354 flowInfo.Flow.FlowType == Downstream &&
3355 flowInfo.Flow.Classifier.OVid > 0 &&
3356 flowInfo.Flow.TechProfileId > 0 {
3357 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3358 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3359 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3360 }
3361 } else if flowInfo.Flow.Classifier.PktTagType == SingleTag &&
3362 flowInfo.Flow.FlowType == Upstream &&
3363 flowInfo.Flow.Action.OVid > 0 &&
3364 flowInfo.Flow.TechProfileId > 0 {
3365 key := subscriberDataPathFlowIDKey{intfID: onu.IntfID, onuID: onu.OnuID, uniID: uniID, direction: flowInfo.Flow.FlowType, tpID: flowInfo.Flow.TechProfileId}
3366 if _, ok := f.subscriberDataPathFlowIDMap[key]; !ok {
3367 f.subscriberDataPathFlowIDMap[key] = flowInfo.Flow.FlowId
3368 }
3369 }
3370 }
3371 }
3372 }
3373}
3374
3375// isDatapathFlow declares a flow as datapath flow if it is not a controller bound flow and the flow does not have group
3376func isDatapathFlow(flow *ofp.OfpFlowStats) bool {
3377 return !IsControllerBoundFlow(flows.GetOutPort(flow)) && !flows.HasGroup(flow)
3378}