blob: b06af008e17b977a50845bd74019d49e1d5f2f6a [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
Joey Armstronga6af1522023-01-17 16:06:16 -05002 * Copyright 2018-2023 Open Networking Foundation (ONF) and the ONF Contributors
manikkaraj kbf256be2019-03-25 00:13:48 +05303
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdraffa52e52022-02-16 15:48:10 -080094 //EthSrc constant
95 EthSrc = "eth_src"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 //TPID constant
97 TPID = "tpid"
98 //IPProto constant
99 IPProto = "ip_proto"
100 //InPort constant
101 InPort = "in_port"
102 //VlanVid constant
103 VlanVid = "vlan_vid"
104 //VlanPcp constant
105 VlanPcp = "vlan_pcp"
106
107 //UDPDst constant
108 UDPDst = "udp_dst"
109 //UDPSrc constant
110 UDPSrc = "udp_src"
111 //Ipv4Dst constant
112 Ipv4Dst = "ipv4_dst"
113 //Ipv4Src constant
114 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700115 //Metadata constant
116 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 //TunnelID constant
118 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700119 //Output constant
120 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000121 //GroupID constant
122 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
125 //PopVlan constant
126 PopVlan = "pop_vlan"
127 //PushVlan constant
128 PushVlan = "push_vlan"
129 //TrapToHost constant
130 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400131 //MaxMeterBand constant
132 MaxMeterBand = 2
133 //VlanPCPMask contant
134 VlanPCPMask = 0xFF
135 //VlanvIDMask constant
136 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000137 //IntfID constant
138 IntfID = "intfId"
139 //OnuID constant
140 OnuID = "onuId"
141 //UniID constant
142 UniID = "uniId"
143 //PortNo constant
144 PortNo = "portNo"
145 //AllocID constant
146 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000147 //GemID constant
148 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000149
150 //NoneOnuID constant
151 NoneOnuID = -1
152 //NoneUniID constant
153 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700154
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700155 // Max number of flows that can be queued per ONU
156 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530157
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700158 bitMapPrefix = "0b"
159 pbit1 = '1'
160)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
163 direction tp_pb.Direction
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 tpID uint32
168 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700169 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000170 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400171 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 portNo uint32
179 classifier map[string]interface{}
180 action map[string]interface{}
181 logicalFlow *ofp.OfpFlowStats
182 allocID uint32
183 gemPortID uint32
184 tpID uint32
185 pbitToGem map[uint32]uint32
186 gemToAes map[uint32]bool
187}
188
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700189// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
190// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
191// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
192// flow and processes it serially
193type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400194 ctx context.Context // Flow handler context
195 addFlow bool // if true flow to be added, else removed
196 flow *ofp.OfpFlowStats // Flow message
197 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
198 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000199}
200
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530202type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700204 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700205 deviceHandler *DeviceHandler
206 grpMgr *OpenOltGroupMgr
207 resourceMgr *rsrcMgr.OpenOltResourceMgr
208
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700212 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
213 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700214 incomingFlows []chan flowControlBlock
215 stopFlowHandlerRoutine []chan bool
216 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530217}
218
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700220func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000221 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530222 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530223 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530224
manikkaraj kbf256be2019-03-25 00:13:48 +0530225 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700226 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700227 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530228 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000229 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
230 if ponPortIdx != dh.totalPonPorts {
231 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
232 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
233 return nil
234 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700237
238 // Create a slice of buffered channels for handling concurrent flows per ONU.
239 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700240 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
241 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
242 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700243 for i := range flowMgr.incomingFlows {
244 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800245 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246 // Spin up a go routine to handling incoming flows (add/remove).
247 // There will be on go routine per ONU.
248 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700249 flowMgr.flowHandlerRoutineActive[i] = true
250 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700252
Esin Karamanccb714b2019-11-29 15:02:06 +0000253 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700254 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000255 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530256 return &flowMgr
257}
258
Kent Hagermane6ff1012020-07-14 15:07:53 -0400259func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000260 // In case of nni trap flow
261 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000262 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
265 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin saplibddc2d72022-02-08 13:10:17 +0000266 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700267 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
268 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
269 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000270 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700271 return err
272 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700273 }
Gamze Abakafee36392019-10-03 11:17:24 +0000274 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 return nil
276}
277
Girish Gowdra9602eb42020-09-09 15:50:39 -0700278func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000279 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400280 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000281 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530282 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700283 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530284
Neha Sharma96b7bf22020-06-15 10:37:32 +0000285 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530286 "device-id": f.deviceHandler.device.Id,
287 "intf-id": intfID,
288 "onu-id": onuID,
289 "uni-id": uniID,
290 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700291 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530292 "action": actionInfo,
293 "usmeter-iD": UsMeterID,
294 "dsmeter-iD": DsMeterID,
295 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400296 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
297 // is because the flow is an NNI flow and there would be no onu resources associated with it
298 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400299 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200300 cause := "no-onu-id-for-flow"
301 fields := log.Fields{
302 "onu": onuID,
303 "port-no": portNo,
304 "classifer": classifierInfo,
305 "action": actionInfo,
306 "device-id": f.deviceHandler.device.Id}
307 logger.Errorw(ctx, cause, fields)
308 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530309 }
310
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700311 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530313 "uni": uni,
314 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530315
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700316 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
317 "device-id": f.deviceHandler.device.Id,
318 "intf-id": intfID,
319 "onu-id": onuID,
320 "uni-id": uniID,
321 "port-no": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo,
324 "usmeter-id": UsMeterID,
325 "dsmeter-id": DsMeterID,
326 "tp-id": TpID})
327 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
328 if allocID == 0 || gemPorts == nil || TpInst == nil {
329 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
330 return olterrors.NewErrNotFound(
331 "alloc-id-gem-ports-tp-unavailable",
332 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700334 args := make(map[string]uint32)
335 args[IntfID] = intfID
336 args[OnuID] = onuID
337 args[UniID] = uniID
338 args[PortNo] = portNo
339 args[AllocID] = allocID
340
341 /* Flows can be added specific to gemport if p-bits are received.
342 * If no pbit mentioned then adding flows for all gemports
343 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000344 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345}
346
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800348// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530349func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400350
Girish Gowdraf3728b12022-02-02 21:46:51 -0800351 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530352 log.Fields{"dir": sq.direction,
353 "intf-id": sq.intfID,
354 "onu-id": sq.onuID,
355 "uni-id": sq.uniID,
356 "tp-id": sq.tpID,
357 "meter-id": sq.meterID,
358 "tp-inst": sq.tpInst,
359 "flowmetadata": sq.flowMetadata,
360 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361
Girish Gowdra6071f382021-12-14 12:52:04 +0530362 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000363 if err != nil {
364 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 }
366
Girish Gowdraf3728b12022-02-02 21:46:51 -0800367 var TrafficShaping *tp_pb.TrafficShapingInfo
368 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
369 return olterrors.NewErrInvalidValue(log.Fields{
370 "reason": "invalid-meter-config",
371 "meter-id": sq.meterID,
372 "device-id": f.deviceHandler.device.Id}, nil)
373 }
374
375 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
376 return olterrors.NewErrInvalidValue(log.Fields{
377 "reason": "invalid-meter-config",
378 "meter-id": sq.meterID,
379 "device-id": f.deviceHandler.device.Id}, nil)
380 }
381
382 var SchedCfg *tp_pb.SchedulerConfig
383 if sq.direction == tp_pb.Direction_UPSTREAM {
384 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
385 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
386 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
387 }
388 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
389 TrafficSched[0].TechProfileId = sq.tpID
390
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 /* Lets make a simple assumption that if the meter-id is present on the KV store,
392 * then the scheduler and queues configuration is applied on the OLT device
393 * in the given direction.
394 */
yasin saplibddc2d72022-02-08 13:10:17 +0000395 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530397 return olterrors.NewErrNotFound("meter",
398 log.Fields{"intf-id": sq.intfID,
399 "onu-id": sq.onuID,
400 "uni-id": sq.uniID,
401 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000403
Girish Gowdraf3728b12022-02-02 21:46:51 -0800404 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530405 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800406 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530407 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000408 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800409 return err
410 }
411
412 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
413 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
414 // Just create gem ports and traffic queues on the current uni for the given service
415 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "tp-id": sq.tpID,
420 "device-id": f.deviceHandler.device.Id})
421 // The upstream scheduler is already created. We only need to create the queues
422 // If there are multiple upstream flows on a given uni, then it is possible that
423 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
424 // TODO: Find better mechanism to not duplicate request.
425 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
426 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
427 log.Fields{"intf-id": sq.intfID,
428 "direction": sq.direction,
429 "device-id": f.deviceHandler.device.Id}, err)
430 }
431 } else {
432 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
433 log.Fields{"intf-id": sq.intfID,
434 "onu-id": sq.onuID,
435 "uni-id": sq.uniID,
436 "tp-id": sq.tpID,
437 "device-id": f.deviceHandler.device.Id})
438 }
439 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000441
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530443 log.Fields{
444 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530445 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447
Girish Gowdraa482f272021-03-24 23:04:19 -0700448 found := false
449 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000450 if sq.flowMetadata != nil {
451 for _, meter := range sq.flowMetadata.Meters {
452 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700453 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700454 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700456 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530457 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 break
460 }
461 }
462 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000463 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530466 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 "reason": "Could-not-get-meterbands-from-flowMetadata",
468 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530469 "meter-id": sq.meterID,
470 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Gamze Abaka01174422021-03-10 06:55:27 +0000472
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700473 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530474 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
475 log.Fields{"intf-id": sq.intfID,
476 "direction": sq.direction,
477 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
479
salmansiddiqui7ac62132019-08-22 03:58:50 +0000480 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 * store the meter id on the KV store, for further reference.
482 */
yasin saplibddc2d72022-02-08 13:10:17 +0000483 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530484 return olterrors.NewErrAdapter("failed-updating-meter-id",
485 log.Fields{"onu-id": sq.onuID,
486 "meter-id": sq.meterID,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530490 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700491 "meter-info": meterInfo,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 return nil
494}
495
Girish Gowdraf3728b12022-02-02 21:46:51 -0800496func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
497 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
498 if err != nil {
499 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
503 }
504 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
505 log.Fields{"direction": sq.direction,
506 "traffic-queues": trafficQueues,
507 "device-id": f.deviceHandler.device.Id})
508 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
509 UniId: sq.uniID, PortNo: sq.uniPort,
510 TrafficQueues: trafficQueues,
511 TechProfileId: TrafficSched[0].TechProfileId}
512 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
513 if len(queues.TrafficQueues) > 1 {
514 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
515 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
516 }
517 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
518 }
519 return err
520}
521
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700522func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700523 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000524
525 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530526 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
527 log.Fields{"intf-id": sq.intfID,
528 "direction": sq.direction,
529 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000530 }
531
Gamze Abakacb0e6772021-06-10 08:32:12 +0000532 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
533 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
534 log.Fields{
535 "direction": sq.direction,
536 "TrafficScheds": TrafficSched,
537 "device-id": f.deviceHandler.device.Id,
538 "intfID": sq.intfID,
539 "onuID": sq.onuID,
540 "uniID": sq.uniID})
541 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
542 IntfId: sq.intfID, OnuId: sq.onuID,
543 UniId: sq.uniID, PortNo: sq.uniPort,
544 TrafficScheds: TrafficSched}); err != nil {
545 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
546 }
547 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
548 "direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551 }
552
553 // On receiving the CreateTrafficQueues request, the driver should create corresponding
554 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530556 log.Fields{"direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000559 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
560 UniId: sq.uniID, PortNo: sq.uniPort,
561 TrafficQueues: trafficQueues,
562 TechProfileId: TrafficSched[0].TechProfileId}
563 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
564 if len(queues.TrafficQueues) > 1 {
565 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
566 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
567 }
568 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530569 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000571 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530572 "direction": sq.direction,
573 "traffic-queues": trafficQueues,
574 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700577 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000578 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700579 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
581 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 gemPortID: multicastQueuePerPonPort.GemportId,
586 servicePriority: multicastQueuePerPonPort.Priority,
587 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700588 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 //also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000590 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700591 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400592 return err
593 }
Shrey Baid26912972020-04-16 21:02:31 +0530594
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 }
597 }
598 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599 return nil
600}
601
Girish Gowdraf3728b12022-02-02 21:46:51 -0800602// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
603func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
604 var err error
605 logger.Infow(ctx, "removing-queue-in-olt",
606 log.Fields{
607 "direction": sq.direction,
608 "intf-id": sq.intfID,
609 "onu-id": sq.onuID,
610 "uni-id": sq.uniID,
611 "uni-port": sq.uniPort,
612 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613
Girish Gowdraf3728b12022-02-02 21:46:51 -0800614 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
615 if err != nil {
616 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
617 log.Fields{
618 "intf-id": sq.intfID,
619 "direction": sq.direction,
620 "device-id": f.deviceHandler.device.Id}, err)
621 }
622
623 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
624 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
625 UniId: sq.uniID, PortNo: sq.uniPort,
626 TrafficQueues: TrafficQueues,
627 TechProfileId: sq.tpID}); err != nil {
628 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
629 log.Fields{
630 "intf-id": sq.intfID,
631 "traffic-queues": TrafficQueues,
632 "device-id": f.deviceHandler.device.Id}, err)
633 }
634 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
635
636 return err
637}
638
639// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
640func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 var Direction string
642 var SchedCfg *tp_pb.SchedulerConfig
643 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800644 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530645 log.Fields{
646 "direction": sq.direction,
647 "intf-id": sq.intfID,
648 "onu-id": sq.onuID,
649 "uni-id": sq.uniID,
650 "uni-port": sq.uniPort,
651 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000652 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700653 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000655 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700656 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400657 Direction = "downstream"
658 }
659
Girish Gowdraa482f272021-03-24 23:04:19 -0700660 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700662 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664
Girish Gowdraf3728b12022-02-02 21:46:51 -0800665 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
666 IntfId: sq.intfID, OnuId: sq.onuID,
667 UniId: sq.uniID, PortNo: sq.uniPort,
668 TrafficScheds: TrafficSched}); err != nil {
669 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530670 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800671 "intf-id": sq.intfID,
672 "traffic-schedulers": TrafficSched,
673 "onu-id": sq.onuID,
674 "uni-id": sq.uniID,
675 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000676 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
679 log.Fields{"device-id": f.deviceHandler.device.Id,
680 "intf-id": sq.intfID,
681 "onu-id": sq.onuID,
682 "uni-id": sq.uniID,
683 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684
Girish Gowdraf3728b12022-02-02 21:46:51 -0800685 if sq.direction == tp_pb.Direction_UPSTREAM {
686 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
687 // Delete the TCONT on the ONU.
688 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000689 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800690 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
691 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000692 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800693 "intf": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "device-id": f.deviceHandler.device.Id,
697 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000698 }
699 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000700
701 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 * delete the meter id on the KV store.
703 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800704 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 return err
706}
707
Girish Gowdra197acc12021-08-16 10:59:45 -0700708// We are trying to force remove the schedulers and queues here if one exists for the given key.
709// We ignore any errors encountered in the process. The errors most likely are encountered when
710// the schedulers and queues are already cleared for the given key.
711func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
712
713 var schedCfg *tp_pb.SchedulerConfig
714 var err error
715 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
716 log.Fields{
717 "direction": sq.direction,
718 "intf-id": sq.intfID,
719 "onu-id": sq.onuID,
720 "uni-id": sq.uniID,
721 "uni-port": sq.uniPort,
722 "tp-id": sq.tpID,
723 "device-id": f.deviceHandler.device.Id})
724 if sq.direction == tp_pb.Direction_UPSTREAM {
725 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
726 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
727 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
728 }
729
730 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
731 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
732 TrafficSched[0].TechProfileId = sq.tpID
733
734 // Remove traffic queues. Ignore any errors, just log them.
735 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
736 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
737 "direction": sq.direction,
738 "intf-id": sq.intfID,
739 "onu-id": sq.onuID,
740 "uni-id": sq.uniID,
741 "uni-port": sq.uniPort,
742 "tp-id": sq.tpID,
743 "device-id": f.deviceHandler.device.Id,
744 "err": err})
745 } else {
746 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
747 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
748 UniId: sq.uniID, PortNo: sq.uniPort,
749 TrafficQueues: TrafficQueues,
750 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
751 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
752 "direction": sq.direction,
753 "intf-id": sq.intfID,
754 "onu-id": sq.onuID,
755 "uni-id": sq.uniID,
756 "uni-port": sq.uniPort,
757 "tp-id": sq.tpID,
758 "device-id": f.deviceHandler.device.Id,
759 "err": err})
760
761 } else {
762 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
763 "direction": sq.direction,
764 "intf-id": sq.intfID,
765 "onu-id": sq.onuID,
766 "uni-id": sq.uniID,
767 "uni-port": sq.uniPort,
768 "tp-id": sq.tpID})
769 }
770 }
771
772 // Remove traffic schedulers. Ignore any errors, just log them.
773 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
774 IntfId: sq.intfID, OnuId: sq.onuID,
775 UniId: sq.uniID, PortNo: sq.uniPort,
776 TrafficScheds: TrafficSched}); err != nil {
777 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
778 "direction": sq.direction,
779 "intf-id": sq.intfID,
780 "onu-id": sq.onuID,
781 "uni-id": sq.uniID,
782 "uni-port": sq.uniPort,
783 "tp-id": sq.tpID,
784 "device-id": f.deviceHandler.device.Id,
785 "err": err})
786 } else {
787 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
788 "direction": sq.direction,
789 "intf-id": sq.intfID,
790 "onu-id": sq.onuID,
791 "uni-id": sq.uniID,
792 "uni-port": sq.uniPort,
793 "tp-id": sq.tpID})
794 }
795}
796
Gamze Abakafee36392019-10-03 11:17:24 +0000797// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400798func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000799 var allocIDs []uint32
800 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530802 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000803 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000804 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
805 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
806 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530807
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530809 "intf-id": intfID,
810 "onu-id": onuID,
811 "uni-id": uniID,
812 "device-id": f.deviceHandler.device.Id,
813 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530814
Manikkaraj kb1d51442019-07-23 10:41:02 -0400815 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700816 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000817 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530819 log.Fields{
820 "path": tpPath,
821 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700822 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000823 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530824 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530826 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700827 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530828 "tp-id": TpID,
829 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000830 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
yasin saplibddc2d72022-02-08 13:10:17 +0000832 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700833 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400834 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530837 log.Fields{
838 "uni": uni,
839 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530840 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530841 }
Gamze Abakafee36392019-10-03 11:17:24 +0000842
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700844 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700845 if UsMeterID != 0 {
846 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
847 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
848 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700851 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700852 "onu-id": onuID,
853 "uni-id": uniID,
854 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 "meter-id": UsMeterID,
856 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000857 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700858 return 0, nil, nil
859 }
860 }
861 if DsMeterID != 0 {
862 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
863 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
864 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700868 "onu-id": onuID,
869 "uni-id": uniID,
870 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 "meter-id": DsMeterID,
872 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000873 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 return 0, nil, nil
875 }
876 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700879 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700881 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000882
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700883 if tpInstanceExists {
884 return allocID, gemPortIDs, techProfileInstance
885 }
886
887 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700888 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000890 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700892 "intf-id": intfID,
893 "onu-id": onuID,
894 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 "alloc-ids": allocIDs,
896 "gemports": allgemPortIDs,
897 "device-id": f.deviceHandler.device.Id})
898 // Send Tconts and GEM ports to KV store
899 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530900 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400901 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 // CreateSchedulerQueues for EPON needs to be implemented here
903 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700906 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700908 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909
910 if tpInstanceExists {
911 return allocID, gemPortIDs, techProfileInstance
912 }
913
914 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700915 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 log.Fields{
919 "alloc-ids": allocIDs,
920 "gemports": allgemPortIDs,
921 "device-id": f.deviceHandler.device.Id})
922 // Send Tconts and GEM ports to KV store
923 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
924 return allocID, gemPortIDs, techProfileInstance
925 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700927 log.Fields{
928 "tpInst": tpInst})
929 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530930 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530931}
932
npujarec5762e2020-01-01 14:08:48 +0530933func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530934
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530936 log.Fields{
937 "intf-id": intfID,
938 "onu-id": onuID,
939 "uni-id": uniID,
940 "alloc-id": allocID,
941 "gemport-ids": gemPortIDs,
942 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530943 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000944 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000945 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "allocID": allocID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530946 }
yasin saplibddc2d72022-02-08 13:10:17 +0000947 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000948 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530949 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950
Neha Sharma96b7bf22020-06-15 10:37:32 +0000951 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 -0400952 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000953 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000954 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
955 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400956 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530957}
958
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700959func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000961 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700962 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
963 var err error
964 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
965 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
966 if err != nil || f.techprofile == nil {
967 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
968 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
969 }
970 logger.Debugw(ctx, "init-tech-profile-done",
971 log.Fields{
972 "intf-id": intfID,
973 "device-id": f.deviceHandler.device.Id})
974 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700975 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 }
977 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700978 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
979 return fmt.Errorf("pon-port-idx-not-found-in-the-device-info-pon-port-range-%v", f.ponPortIdx)
manikkaraj kbf256be2019-03-25 00:13:48 +0530980}
981
Gamze Abaka7650be62021-02-26 10:50:36 +0000982func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800983 flowContext.classifier[PacketTagType] = SingleTag
984 // extract the cvid/inner-vid from the write metadata
985 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
986 if writeMetadata != 0 {
987 // Writemetadata field is 8 bytes
988 // cvid is on the outer most two bytes of the write metadata
989 cvid := (writeMetadata & 0xffff000000000000) >> 48
990 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
991 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
992 flowContext.classifier[PacketTagType] = DoubleTag
993 }
994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530996 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 "uplinkClassifier": flowContext.classifier,
998 "uplinkAction": flowContext.action})
999 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301000}
1001
Gamze Abaka7650be62021-02-26 10:50:36 +00001002func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1003 downlinkClassifier := flowContext.classifier
1004 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001005 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1006 downlinkClassifier[PacketTagType] = SingleTag
1007 // extract the cvid/inner-vid from the write metadata
1008 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1009 if writeMetadata != 0 {
1010 // Writemetadata field is 8 bytes
1011 // cvid is on the outer most two bytes of the write metadata
1012 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1013 downlinkClassifier[PacketTagType] = DoubleTag
1014 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301015 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301017 log.Fields{
1018 "downlinkClassifier": downlinkClassifier,
1019 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001020
Girish Gowdraffa52e52022-02-16 15:48:10 -08001021 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1022 // The matched vlan is the one that is getting popped.
1023 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1024 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1025 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1026 if ok {
1027 downlinkAction[VlanVid] = dlClVid & 0xfff
1028 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301029 }
1030
Gamze Abaka7650be62021-02-26 10:50:36 +00001031 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301032}
1033
Gamze Abaka7650be62021-02-26 10:50:36 +00001034func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001035
Gamze Abaka7650be62021-02-26 10:50:36 +00001036 intfID := flowContext.intfID
1037 onuID := flowContext.onuID
1038 uniID := flowContext.uniID
1039 classifier := flowContext.classifier
1040 action := flowContext.action
1041 allocID := flowContext.allocID
1042 gemPortID := flowContext.gemPortID
1043 tpID := flowContext.tpID
1044 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301046 log.Fields{
1047 "intf-id": intfID,
1048 "onu-id": onuID,
1049 "uni-id": uniID,
1050 "device-id": f.deviceHandler.device.Id,
1051 "classifier": classifier,
1052 "action": action,
1053 "direction": direction,
1054 "alloc-id": allocID,
1055 "gemport-id": gemPortID,
1056 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001057
yasin saplibddc2d72022-02-08 13:10:17 +00001058 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001059 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301061 log.Fields{
1062 "device-id": f.deviceHandler.device.Id,
1063 "intf-id": intfID,
1064 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 return nil
yasin saplid0566272021-12-21 09:10:30 +00001066 } else if err != nil {
1067 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1068 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1069 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301070 }
yasin saplid0566272021-12-21 09:10:30 +00001071
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 classifierProto, err := makeOpenOltClassifierField(classifier)
1073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "classifier": *classifierProto,
1079 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001080 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "action": *actionProto,
1087 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 log.Fields{
1092 "classifier": classifier,
1093 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301094 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301096 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001099 OnuId: int32(onuID),
1100 UniId: int32(uniID),
1101 FlowId: logicalFlow.Id,
1102 FlowType: direction,
1103 AllocId: int32(allocID),
1104 NetworkIntfId: int32(networkIntfID),
1105 GemportId: int32(gemPortID),
1106 Classifier: classifierProto,
1107 Action: actionProto,
1108 Priority: int32(logicalFlow.Priority),
1109 Cookie: logicalFlow.Cookie,
1110 PortNo: flowContext.portNo,
1111 TechProfileId: tpID,
1112 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1113 PbitToGemport: flowContext.pbitToGem,
1114 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001115 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301120 log.Fields{"direction": direction,
1121 "device-id": f.deviceHandler.device.Id,
1122 "flow": flow,
1123 "intf-id": intfID,
1124 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301127}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128
Gamze Abaka7650be62021-02-26 10:50:36 +00001129func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1130
1131 intfID := flowContext.intfID
1132 onuID := flowContext.onuID
1133 uniID := flowContext.uniID
1134 logicalFlow := flowContext.logicalFlow
1135 classifier := flowContext.classifier
1136 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301139 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301142 "action": action,
1143 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
1147 // Clear the action map
1148 for k := range action {
1149 delete(action, k)
1150 }
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 action[TrapToHost] = true
1153 classifier[UDPSrc] = uint32(68)
1154 classifier[UDPDst] = uint32(67)
1155 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
yasin saplibddc2d72022-02-08 13:10:17 +00001157 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001158 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301160 log.Fields{
1161 "device-id": f.deviceHandler.device.Id,
1162 "intf-id": intfID,
1163 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 return nil
yasin saplid0566272021-12-21 09:10:30 +00001165 } else if err != nil {
1166 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1167 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1168 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301169 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "ul_classifier": classifier,
1174 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "intf-id": intfID,
1177 "onu-id": onuID,
1178 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 classifierProto, err := makeOpenOltClassifierField(classifier)
1181 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301182 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001185 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301187 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 }
1189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 OnuId: int32(onuID),
1192 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001194 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001195 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001197 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198 Classifier: classifierProto,
1199 Action: actionProto,
1200 Priority: int32(logicalFlow.Priority),
1201 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 PortNo: flowContext.portNo,
1203 TechProfileId: flowContext.tpID,
1204 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1205 PbitToGemport: flowContext.pbitToGem,
1206 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001207 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001214 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301215 "intf-id": intfID,
1216 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301217
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301219}
1220
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001222func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1223 delete(flowContext.classifier, VlanVid)
1224 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225}
1226
1227//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001228func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1229
1230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
yasin saplibddc2d72022-02-08 13:10:17 +00001255 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001256 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
yasin saplid0566272021-12-21 09:10:30 +00001259 } else if err != nil {
1260 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1261 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1262 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "ul_classifier": classifier,
1268 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301270 "device-id": f.deviceHandler.device.Id,
1271 "intf-id": intfID,
1272 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 classifierProto, err := makeOpenOltClassifierField(classifier)
1275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "classifier": *classifierProto,
1281 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001282 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301284 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 }
1286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 OnuId: int32(onuID),
1289 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001292 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 Classifier: classifierProto,
1296 Action: actionProto,
1297 Priority: int32(logicalFlow.Priority),
1298 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 PortNo: flowContext.portNo,
1300 TechProfileId: flowContext.tpID,
1301 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1302 PbitToGemport: flowContext.pbitToGem,
1303 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307 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 -08001308 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001340 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001346 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001347 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301349 "device-id": f.deviceHandler.device.Id,
1350 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 "intf-id": intfID,
1352 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
yasin saplid0566272021-12-21 09:10:30 +00001354 } else if err != nil {
1355 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1356 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1357 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301358 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001359 //Add Uplink EthType Flow
1360 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "ul_classifier": uplinkClassifier,
1363 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "intf-id": intfID,
1367 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1370 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301371 return olterrors.NewErrInvalidValue(log.Fields{
1372 "classifier": uplinkClassifier,
1373 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "classifier": *classifierProto,
1378 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001379 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301381 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "action": *actionProto,
1386 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301391 "action": action,
1392 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 }
1395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 OnuId: int32(onuID),
1398 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001399 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 AllocId: int32(allocID),
1402 NetworkIntfId: int32(networkIntfID),
1403 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 Classifier: classifierProto,
1405 Action: actionProto,
1406 Priority: int32(logicalFlow.Priority),
1407 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001409 TechProfileId: flowContext.tpID,
1410 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1411 PbitToGemport: flowContext.pbitToGem,
1412 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301418 log.Fields{
1419 "device-id": f.deviceHandler.device.Id,
1420 "onu-id": onuID,
1421 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001422 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301423 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001439 // The classifierInfo[Metadata] is set for the following flows
1440 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1441 // - Mcast flow that points to a group in the treatment
1442 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1443 // - inner vid for a double tagged packet in the datapath flow
1444 // - outer vid for a single tagged packet in the datapath flow
1445 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1447 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301448 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1449 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1450 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1451 // becomes the IVid.
1452 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1453 if vid != ReservedVlan {
1454 classifier.IVid = vid
1455 }
1456 } else {
1457 if vid != ReservedVlan {
1458 classifier.OVid = vid
1459 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001460 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301462 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001463 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301464 classifier.OPbits = vlanPcp
1465 } else {
1466 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001468 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1469 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1470 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1471 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001472 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001473 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001474 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1475 classifier.PktTagType = pktTagType
1476
1477 switch pktTagType {
1478 case SingleTag:
1479 case DoubleTag:
1480 case Untagged:
1481 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001482 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
1484 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301486}
1487
Gamze Abaka724d0852020-03-18 12:10:24 +00001488func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001489 var actionCmd openoltpb2.ActionCmd
1490 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301491 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001492 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001493 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301494 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001495 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001496 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001497 action.Cmd.RemarkInnerPbits = true
1498 action.IPbits = actionInfo[VlanPcp].(uint32)
1499 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001500 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001501 action.Cmd.TranslateInnerTag = true
1502 action.IVid = actionInfo[VlanVid].(uint32)
1503 }
1504 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001506 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301508 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001509 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001510 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001511 action.OPbits = actionInfo[VlanPcp].(uint32)
1512 action.Cmd.RemarkOuterPbits = true
1513 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001514 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001515 action.IVid = classifierInfo[VlanVid].(uint32)
1516 action.Cmd.TranslateInnerTag = true
1517 }
1518 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 } else if _, ok := actionInfo[TrapToHost]; ok {
1520 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001521 } else if _, ok := actionInfo[VlanVid]; ok {
1522 // Translate outer vid
1523 action.Cmd.TranslateOuterTag = true
1524 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301525 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301526 // When OLT is transparent to vlans no-action is valid.
1527 /*
1528 else {
1529 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1530 }
1531 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001532 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301533}
1534
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001535// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001536func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001537 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301538}
1539
Gamze Abakafee36392019-10-03 11:17:24 +00001540// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001541// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1542// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1543// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1544// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1545// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1546// because it was observed that if the ONU device was deleted too soon after the flows were
1547// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1548// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1549// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001550func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001551 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001552 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1553
Gamze Abakafee36392019-10-03 11:17:24 +00001554 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001555
1556 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001557 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001558 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001559 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001560 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1561 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1562 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1563 log.Fields{
1564 "tp-id": tpID,
1565 "path": tpPath})
1566 }
1567 switch tpInstance := tpInst.(type) {
1568 case *tp_pb.TechProfileInstance:
1569 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1570 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1571 }
1572 // Force cleanup scheduler/queues -- end
1573
1574 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301575 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001576 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301577 // return err
1578 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001579 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001580 logger.Debugw(ctx, "tech-profile-instance-deleted", log.Fields{"device-id": f.deviceHandler.device.Id, "uniPortName": uniPortName, "tp-id": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001581 }
1582 return nil
1583}
1584
1585// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301586func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001587 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001588 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001589 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301591 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1592 log.Fields{
1593 "tp-id": tpID,
1594 "uni-port-name": uniPortName,
1595 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001596 }
1597 return nil
1598}
1599
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001601
1602 var intfID uint32
1603 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1604 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1605 */
1606 if deviceFlow.AccessIntfId != -1 {
1607 intfID = uint32(deviceFlow.AccessIntfId)
1608 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001609 // We need to log the valid interface ID.
1610 // 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 +00001611 intfID = uint32(deviceFlow.NetworkIntfId)
1612 }
1613
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001618 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001619
1620 st, _ := status.FromError(err)
1621 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001623 "err": err,
1624 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301625 "device-id": f.deviceHandler.device.Id,
1626 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301628 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301632 log.Fields{"err": err,
1633 "device-flow": deviceFlow,
1634 "device-id": f.deviceHandler.device.Id,
1635 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001637 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301639 log.Fields{
1640 "flow": *deviceFlow,
1641 "device-id": f.deviceHandler.device.Id,
1642 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001643
yasin saplid0566272021-12-21 09:10:30 +00001644 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1645 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1646 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001647 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001649}
1650
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1652 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301653 log.Fields{
1654 "flow": *deviceFlow,
1655 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001656 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001657 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001658 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "err": err,
1662 "deviceFlow": deviceFlow,
1663 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001664 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001666 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001667 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001668
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001669 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001671 "of-flow-id": ofFlowID,
1672 "flow": *deviceFlow,
1673 "device-id": f.deviceHandler.device.Id,
1674 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301676}
1677
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001679
1680 classifierInfo := make(map[string]interface{})
1681 actionInfo := make(map[string]interface{})
1682
1683 classifierInfo[EthType] = uint32(LldpEthType)
1684 classifierInfo[PacketTagType] = Untagged
1685 actionInfo[TrapToHost] = true
1686
1687 // LLDP flow is installed to trap LLDP packets on the NNI port.
1688 // We manage flow_id resource pool on per PON port basis.
1689 // Since this situation is tricky, as a hack, we pass the NNI port
1690 // index (network_intf_id) as PON port Index for the flow_id resource
1691 // pool. Also, there is no ONU Id available for trapping LLDP packets
1692 // on NNI port, use onu_id as -1 (invalid)
1693 // ****************** CAVEAT *******************
1694 // This logic works if the NNI Port Id falls within the same valid
1695 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1696 // we need to have a re-look at this.
1697 // *********************************************
1698
1699 var onuID = -1
1700 var uniID = -1
1701 var gemPortID = -1
1702
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001703 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301705 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 }
yasin saplibddc2d72022-02-08 13:10:17 +00001707 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001708 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 return nil
yasin saplid0566272021-12-21 09:10:30 +00001711 } else if err != nil {
1712 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1713 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1714 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001715 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001716
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1718 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301719 return olterrors.NewErrInvalidValue(
1720 log.Fields{
1721 "classifier": classifierInfo,
1722 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001723 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "classifier": *classifierProto,
1727 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001728 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001729 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301730 return olterrors.NewErrInvalidValue(
1731 log.Fields{
1732 "action": actionInfo,
1733 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001734 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301736 log.Fields{
1737 "action": *actionProto,
1738 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001739
1740 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1741 OnuId: int32(onuID), // OnuId not required
1742 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001743 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 FlowType: Downstream,
1745 NetworkIntfId: int32(networkInterfaceID),
1746 GemportId: int32(gemPortID),
1747 Classifier: classifierProto,
1748 Action: actionProto,
1749 Priority: int32(flow.Priority),
1750 Cookie: flow.Cookie,
1751 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001753 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301754 log.Fields{
1755 "flow": downstreamflow,
1756 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301759 log.Fields{
1760 "device-id": f.deviceHandler.device.Id,
1761 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001762 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001763
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301765}
1766
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001767func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1768 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769}
1770
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001773 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1774 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1775 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001782 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301783 return nil, olterrors.NewErrNotFound("onu-child-device",
1784 log.Fields{
1785 "onu-id": onuID,
1786 "intf-id": intfID,
1787 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001788 }
khenaidoo106c61a2021-08-11 18:05:46 -04001789 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001790 //better to ad the device to cache here.
1791 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1792 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001793 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301794 log.Fields{
1795 "intf-id": intfID,
1796 "onu-id": onuID,
1797 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
1799
1800 return onuDev.(*OnuDevice), nil
1801}
1802
1803//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1805 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
1807 "pon-port": intfID,
1808 "onu-id": onuID,
1809 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001810 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001812 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301813 return nil, olterrors.NewErrNotFound("onu",
1814 log.Fields{
1815 "interface-id": parentPortNo,
1816 "onu-id": onuID,
1817 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001818 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301819 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "device-id": f.deviceHandler.device.Id,
1823 "child_device_id": onuDevice.Id,
1824 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301825 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301826}
1827
Neha Sharma96b7bf22020-06-15 10:37:32 +00001828func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1829 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301830 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001831 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301832 log.Fields{
1833 "intf-id": intfID,
1834 "onu-id": onuID,
1835 "uni-id": uniID,
1836 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001837 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301838 }
1839
khenaidoodc2116e2021-10-19 17:33:19 -04001840 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001841 DeviceId: onuDev.deviceID,
1842 UniId: uniID,
1843 TpInstancePath: tpPath,
1844 GemPortId: gemPortID,
1845 }
1846 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1847
1848 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301849 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1850 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001851 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1852 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301853 "onu-id": onuDev.deviceID,
1854 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001855 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301856 }
khenaidoo106c61a2021-08-11 18:05:46 -04001857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301859 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001860 "msg": delGemPortMsg,
1861 "from-adapter": f.deviceHandler.device.Type,
1862 "to-adapter": onuDev.deviceType,
1863 "device-id": f.deviceHandler.device.Id,
1864 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301865 return nil
1866}
1867
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1869 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301870 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301872 log.Fields{
1873 "intf-id": intfID,
1874 "onu-id": onuID,
1875 "uni-id": uniID,
1876 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001877 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301878 }
1879
khenaidoodc2116e2021-10-19 17:33:19 -04001880 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001881 DeviceId: onuDev.deviceID,
1882 UniId: uniID,
1883 TpInstancePath: tpPath,
1884 AllocId: allocID,
1885 }
1886
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301888 log.Fields{
1889 "msg": *delTcontMsg,
1890 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001891
1892 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301893 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1894 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001895 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1896 "to-adapter": onuDev.adapterEndpoint,
1897 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301898 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001899 "device-id": f.deviceHandler.device.Id}, err)
1900
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001902 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301903 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001904 "msg": delTcontMsg,
1905 "device-id": f.deviceHandler.device.Id,
1906 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301907 return nil
1908}
1909
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301910//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001911// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001912func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001913 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001914
1915 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001916
Girish Gowdraa482f272021-03-24 23:04:19 -07001917 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001918 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1920 log.Fields{
1921 "tpPath": tpPath,
1922 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001923
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001924 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001925 if err != nil || techprofileInst == nil {
1926 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1927 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1928 if childDevice == nil {
1929 // happens when subscriber un-provision is immediately followed by child device delete
1930 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1931 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1932 return nil
1933 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001934 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1935 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001936 log.Fields{
1937 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001938 "path": tpPath}, err).Log()
1939 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001940 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001941
1942 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001945 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1946 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001947 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1948 if err != nil {
1949 return err
1950 }
1951 used := false
1952 for _, id := range flowIDs {
1953 if flowID != id {
1954 used = true
1955 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001956 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001957 }
1958 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001959 for i, flowIDinMap := range flowIDs {
1960 if flowIDinMap == flowID {
1961 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001962 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001963 return err
1964 }
1965 break
1966 }
1967 }
1968 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1969 log.Fields{
1970 "gemport-id": gemPortID,
1971 "usedByFlows": flowIDs,
1972 "currentFlow": flowID,
1973 "device-id": f.deviceHandler.device.Id})
1974 allGemPortsFree = false
1975 }
1976 }
1977 if !allGemPortsFree {
1978 return nil
1979 }
1980 }
1981
1982 logger.Debugw(ctx, "all-gem-ports-are-free-to-be-deleted", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Girish Gowdraf3728b12022-02-02 21:46:51 -08001983
1984 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
Gamze Abaka745ccb72021-11-18 11:29:58 +00001985 switch techprofileInst := techprofileInst.(type) {
1986 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001987 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1988 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001989 _ = f.res