blob: f910cc26ee3d2061d0e1ac47f8f505881b9da9ce [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
Joey Armstrong3f0e2422023-07-05 18:25:41 -040017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package 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
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400201// 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
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000219// CloseKVClient closes open KV clients
220func (f *OpenOltFlowMgr) CloseKVClient(ctx context.Context) {
221 if f.techprofile != nil {
222 f.techprofile.CloseKVClient(ctx)
223 }
224}
225
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400226// NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700227func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000228 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530229 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530230 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231
manikkaraj kbf256be2019-03-25 00:13:48 +0530232 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700233 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700234 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530235 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000236 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
237 if ponPortIdx != dh.totalPonPorts {
238 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
239 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
240 return nil
241 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530242 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530243 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700244
245 // Create a slice of buffered channels for handling concurrent flows per ONU.
246 // 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 -0700247 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
248 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
249 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700250 for i := range flowMgr.incomingFlows {
251 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800252 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700253 // Spin up a go routine to handling incoming flows (add/remove).
254 // There will be on go routine per ONU.
255 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700256 flowMgr.flowHandlerRoutineActive[i] = true
257 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700258 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700259
Esin Karamanccb714b2019-11-29 15:02:06 +0000260 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700261 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000262 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530263 return &flowMgr
264}
265
Kent Hagermane6ff1012020-07-14 15:07:53 -0400266func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000267 // In case of nni trap flow
268 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000269 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000270 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700271 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
272 // 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 +0000273 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700274 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
275 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
276 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000277 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700278 return err
279 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700280 }
Gamze Abakafee36392019-10-03 11:17:24 +0000281 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700282 return nil
283}
284
Girish Gowdra9602eb42020-09-09 15:50:39 -0700285func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000286 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400287 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000288 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530289 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700290 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530291
Neha Sharma96b7bf22020-06-15 10:37:32 +0000292 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530293 "device-id": f.deviceHandler.device.Id,
294 "intf-id": intfID,
295 "onu-id": onuID,
296 "uni-id": uniID,
297 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700298 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530299 "action": actionInfo,
300 "usmeter-iD": UsMeterID,
301 "dsmeter-iD": DsMeterID,
302 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400303 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
304 // is because the flow is an NNI flow and there would be no onu resources associated with it
305 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400306 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200307 cause := "no-onu-id-for-flow"
308 fields := log.Fields{
309 "onu": onuID,
310 "port-no": portNo,
311 "classifer": classifierInfo,
312 "action": actionInfo,
313 "device-id": f.deviceHandler.device.Id}
314 logger.Errorw(ctx, cause, fields)
315 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530316 }
317
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700318 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000319 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530320 "uni": uni,
321 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530322
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700323 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
324 "device-id": f.deviceHandler.device.Id,
325 "intf-id": intfID,
326 "onu-id": onuID,
327 "uni-id": uniID,
328 "port-no": portNo,
329 "classifier": classifierInfo,
330 "action": actionInfo,
331 "usmeter-id": UsMeterID,
332 "dsmeter-id": DsMeterID,
333 "tp-id": TpID})
334 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
335 if allocID == 0 || gemPorts == nil || TpInst == nil {
336 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
337 return olterrors.NewErrNotFound(
338 "alloc-id-gem-ports-tp-unavailable",
339 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400340 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700341 args := make(map[string]uint32)
342 args[IntfID] = intfID
343 args[OnuID] = onuID
344 args[UniID] = uniID
345 args[PortNo] = portNo
346 args[AllocID] = allocID
347
348 /* Flows can be added specific to gemport if p-bits are received.
349 * If no pbit mentioned then adding flows for all gemports
350 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000351 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530352}
353
salmansiddiqui7ac62132019-08-22 03:58:50 +0000354// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800355// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530356func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400357
nikesh.krishnan81ec7442023-10-31 17:19:34 +0530358 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530359 log.Fields{"dir": sq.direction,
360 "intf-id": sq.intfID,
361 "onu-id": sq.onuID,
362 "uni-id": sq.uniID,
363 "tp-id": sq.tpID,
364 "meter-id": sq.meterID,
365 "tp-inst": sq.tpInst,
366 "flowmetadata": sq.flowMetadata,
367 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400368
Girish Gowdra6071f382021-12-14 12:52:04 +0530369 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000370 if err != nil {
371 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400372 }
373
Girish Gowdraf3728b12022-02-02 21:46:51 -0800374 var TrafficShaping *tp_pb.TrafficShapingInfo
375 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
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 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
383 return olterrors.NewErrInvalidValue(log.Fields{
384 "reason": "invalid-meter-config",
385 "meter-id": sq.meterID,
386 "device-id": f.deviceHandler.device.Id}, nil)
387 }
388
389 var SchedCfg *tp_pb.SchedulerConfig
390 if sq.direction == tp_pb.Direction_UPSTREAM {
391 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
392 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
393 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
394 }
395 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
396 TrafficSched[0].TechProfileId = sq.tpID
397
Manikkaraj kb1d51442019-07-23 10:41:02 -0400398 /* Lets make a simple assumption that if the meter-id is present on the KV store,
399 * then the scheduler and queues configuration is applied on the OLT device
400 * in the given direction.
401 */
yasin saplibddc2d72022-02-08 13:10:17 +0000402 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400403 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530404 return olterrors.NewErrNotFound("meter",
405 log.Fields{"intf-id": sq.intfID,
406 "onu-id": sq.onuID,
407 "uni-id": sq.uniID,
408 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400409 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000410
Girish Gowdraf3728b12022-02-02 21:46:51 -0800411 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530412 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800413 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530414 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000415 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800416 return err
417 }
418
419 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
420 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
421 // Just create gem ports and traffic queues on the current uni for the given service
422 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
423 log.Fields{"intf-id": sq.intfID,
424 "onu-id": sq.onuID,
425 "uni-id": sq.uniID,
426 "tp-id": sq.tpID,
427 "device-id": f.deviceHandler.device.Id})
428 // The upstream scheduler is already created. We only need to create the queues
429 // If there are multiple upstream flows on a given uni, then it is possible that
430 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
431 // TODO: Find better mechanism to not duplicate request.
432 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
433 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
434 log.Fields{"intf-id": sq.intfID,
435 "direction": sq.direction,
436 "device-id": f.deviceHandler.device.Id}, err)
437 }
438 } else {
439 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
440 log.Fields{"intf-id": sq.intfID,
441 "onu-id": sq.onuID,
442 "uni-id": sq.uniID,
443 "tp-id": sq.tpID,
444 "device-id": f.deviceHandler.device.Id})
445 }
446 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400447 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000448
Neha Sharma96b7bf22020-06-15 10:37:32 +0000449 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530450 log.Fields{
451 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530452 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530453 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000454
Girish Gowdraa482f272021-03-24 23:04:19 -0700455 found := false
456 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000457 if sq.flowMetadata != nil {
458 for _, meter := range sq.flowMetadata.Meters {
459 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700460 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700461 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 +0000462 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530464 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400466 break
467 }
468 }
469 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000470 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700472 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530473 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800474 "reason": "Could-not-get-meterbands-from-flowMetadata",
475 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530476 "meter-id": sq.meterID,
477 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
Gamze Abaka01174422021-03-10 06:55:27 +0000479
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700480 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530481 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
482 log.Fields{"intf-id": sq.intfID,
483 "direction": sq.direction,
484 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400485 }
486
salmansiddiqui7ac62132019-08-22 03:58:50 +0000487 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 * store the meter id on the KV store, for further reference.
489 */
yasin saplibddc2d72022-02-08 13:10:17 +0000490 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530491 return olterrors.NewErrAdapter("failed-updating-meter-id",
492 log.Fields{"onu-id": sq.onuID,
493 "meter-id": sq.meterID,
494 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400495 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000496 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530497 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700498 "meter-info": meterInfo,
499 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400500 return nil
501}
502
Girish Gowdraf3728b12022-02-02 21:46:51 -0800503func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
504 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
505 if err != nil {
506 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
507 log.Fields{"intf-id": sq.intfID,
508 "direction": sq.direction,
509 "device-id": f.deviceHandler.device.Id}, err)
510 }
511 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
512 log.Fields{"direction": sq.direction,
513 "traffic-queues": trafficQueues,
514 "device-id": f.deviceHandler.device.Id})
515 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
516 UniId: sq.uniID, PortNo: sq.uniPort,
517 TrafficQueues: trafficQueues,
518 TechProfileId: TrafficSched[0].TechProfileId}
519 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
520 if len(queues.TrafficQueues) > 1 {
521 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
522 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
523 }
524 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
525 }
526 return err
527}
528
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700529func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700530 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000531
532 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530533 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
534 log.Fields{"intf-id": sq.intfID,
535 "direction": sq.direction,
536 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000537 }
538
Gamze Abakacb0e6772021-06-10 08:32:12 +0000539 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
540 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
541 log.Fields{
542 "direction": sq.direction,
543 "TrafficScheds": TrafficSched,
544 "device-id": f.deviceHandler.device.Id,
545 "intfID": sq.intfID,
546 "onuID": sq.onuID,
547 "uniID": sq.uniID})
548 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
549 IntfId: sq.intfID, OnuId: sq.onuID,
550 UniId: sq.uniID, PortNo: sq.uniPort,
551 TrafficScheds: TrafficSched}); err != nil {
552 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
553 }
554 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
555 "direction": sq.direction,
556 "traffic-queues": trafficQueues,
557 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000558 }
559
560 // On receiving the CreateTrafficQueues request, the driver should create corresponding
561 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530563 log.Fields{"direction": sq.direction,
564 "traffic-queues": trafficQueues,
565 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000566 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
567 UniId: sq.uniID, PortNo: sq.uniPort,
568 TrafficQueues: trafficQueues,
569 TechProfileId: TrafficSched[0].TechProfileId}
570 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
571 if len(queues.TrafficQueues) > 1 {
572 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
573 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
574 }
575 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530576 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000577 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000578 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530579 "direction": sq.direction,
580 "traffic-queues": trafficQueues,
581 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000582
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700584 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700586 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 +0000587 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
588 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000589 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000590 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700591 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000592 gemPortID: multicastQueuePerPonPort.GemportId,
593 servicePriority: multicastQueuePerPonPort.Priority,
594 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700595 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 //also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000597 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700598 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400599 return err
600 }
Shrey Baid26912972020-04-16 21:02:31 +0530601
Neha Sharma96b7bf22020-06-15 10:37:32 +0000602 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 }
604 }
605 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000606 return nil
607}
608
Girish Gowdraf3728b12022-02-02 21:46:51 -0800609// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
610func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
611 var err error
612 logger.Infow(ctx, "removing-queue-in-olt",
613 log.Fields{
614 "direction": sq.direction,
615 "intf-id": sq.intfID,
616 "onu-id": sq.onuID,
617 "uni-id": sq.uniID,
618 "uni-port": sq.uniPort,
619 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400620
Girish Gowdraf3728b12022-02-02 21:46:51 -0800621 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
622 if err != nil {
623 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
624 log.Fields{
625 "intf-id": sq.intfID,
626 "direction": sq.direction,
627 "device-id": f.deviceHandler.device.Id}, err)
628 }
629
630 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
631 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
632 UniId: sq.uniID, PortNo: sq.uniPort,
633 TrafficQueues: TrafficQueues,
634 TechProfileId: sq.tpID}); err != nil {
635 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
636 log.Fields{
637 "intf-id": sq.intfID,
638 "traffic-queues": TrafficQueues,
639 "device-id": f.deviceHandler.device.Id}, err)
640 }
641 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
642
643 return err
644}
645
646// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
647func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648 var Direction string
649 var SchedCfg *tp_pb.SchedulerConfig
650 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800651 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530652 log.Fields{
653 "direction": sq.direction,
654 "intf-id": sq.intfID,
655 "onu-id": sq.onuID,
656 "uni-id": sq.uniID,
657 "uni-port": sq.uniPort,
658 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000659 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700660 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000662 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700663 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400664 Direction = "downstream"
665 }
666
Girish Gowdraa482f272021-03-24 23:04:19 -0700667 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 -0400668
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700669 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000670 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000671
Girish Gowdraf3728b12022-02-02 21:46:51 -0800672 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
673 IntfId: sq.intfID, OnuId: sq.onuID,
674 UniId: sq.uniID, PortNo: sq.uniPort,
675 TrafficScheds: TrafficSched}); err != nil {
676 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530677 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 "intf-id": sq.intfID,
679 "traffic-schedulers": TrafficSched,
680 "onu-id": sq.onuID,
681 "uni-id": sq.uniID,
682 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000683 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684
Girish Gowdraf3728b12022-02-02 21:46:51 -0800685 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
686 log.Fields{"device-id": f.deviceHandler.device.Id,
687 "intf-id": sq.intfID,
688 "onu-id": sq.onuID,
689 "uni-id": sq.uniID,
690 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400691
Girish Gowdraf3728b12022-02-02 21:46:51 -0800692 if sq.direction == tp_pb.Direction_UPSTREAM {
693 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
694 // Delete the TCONT on the ONU.
695 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000696 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800697 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
698 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000699 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800700 "intf": sq.intfID,
701 "onu-id": sq.onuID,
702 "uni-id": sq.uniID,
703 "device-id": f.deviceHandler.device.Id,
704 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000705 }
706 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000707
708 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400709 * delete the meter id on the KV store.
710 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800711 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400712 return err
713}
714
Girish Gowdra197acc12021-08-16 10:59:45 -0700715// We are trying to force remove the schedulers and queues here if one exists for the given key.
716// We ignore any errors encountered in the process. The errors most likely are encountered when
717// the schedulers and queues are already cleared for the given key.
718func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
719
720 var schedCfg *tp_pb.SchedulerConfig
721 var err error
722 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
723 log.Fields{
724 "direction": sq.direction,
725 "intf-id": sq.intfID,
726 "onu-id": sq.onuID,
727 "uni-id": sq.uniID,
728 "uni-port": sq.uniPort,
729 "tp-id": sq.tpID,
730 "device-id": f.deviceHandler.device.Id})
731 if sq.direction == tp_pb.Direction_UPSTREAM {
732 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
733 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
734 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
735 }
736
737 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
738 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
739 TrafficSched[0].TechProfileId = sq.tpID
740
741 // Remove traffic queues. Ignore any errors, just log them.
742 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
743 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
744 "direction": sq.direction,
745 "intf-id": sq.intfID,
746 "onu-id": sq.onuID,
747 "uni-id": sq.uniID,
748 "uni-port": sq.uniPort,
749 "tp-id": sq.tpID,
750 "device-id": f.deviceHandler.device.Id,
751 "err": err})
752 } else {
753 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
754 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
755 UniId: sq.uniID, PortNo: sq.uniPort,
756 TrafficQueues: TrafficQueues,
757 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
758 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
759 "direction": sq.direction,
760 "intf-id": sq.intfID,
761 "onu-id": sq.onuID,
762 "uni-id": sq.uniID,
763 "uni-port": sq.uniPort,
764 "tp-id": sq.tpID,
765 "device-id": f.deviceHandler.device.Id,
766 "err": err})
767
768 } else {
769 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
770 "direction": sq.direction,
771 "intf-id": sq.intfID,
772 "onu-id": sq.onuID,
773 "uni-id": sq.uniID,
774 "uni-port": sq.uniPort,
775 "tp-id": sq.tpID})
776 }
777 }
778
779 // Remove traffic schedulers. Ignore any errors, just log them.
780 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
781 IntfId: sq.intfID, OnuId: sq.onuID,
782 UniId: sq.uniID, PortNo: sq.uniPort,
783 TrafficScheds: TrafficSched}); err != nil {
784 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
785 "direction": sq.direction,
786 "intf-id": sq.intfID,
787 "onu-id": sq.onuID,
788 "uni-id": sq.uniID,
789 "uni-port": sq.uniPort,
790 "tp-id": sq.tpID,
791 "device-id": f.deviceHandler.device.Id,
792 "err": err})
793 } else {
794 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
795 "direction": sq.direction,
796 "intf-id": sq.intfID,
797 "onu-id": sq.onuID,
798 "uni-id": sq.uniID,
799 "uni-port": sq.uniPort,
800 "tp-id": sq.tpID})
801 }
802}
803
Gamze Abakafee36392019-10-03 11:17:24 +0000804// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400805func (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 +0000806 var allocIDs []uint32
807 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530808 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530809 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000810 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000811 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
812 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
813 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530814
Neha Sharma96b7bf22020-06-15 10:37:32 +0000815 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530816 "intf-id": intfID,
817 "onu-id": onuID,
818 "uni-id": uniID,
819 "device-id": f.deviceHandler.device.Id,
820 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530821
Manikkaraj kb1d51442019-07-23 10:41:02 -0400822 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700823 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000824 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530826 log.Fields{
827 "path": tpPath,
828 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700829 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000830 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530831 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000832 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530833 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700834 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530835 "tp-id": TpID,
836 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000837 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530838 }
yasin saplibddc2d72022-02-08 13:10:17 +0000839 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700840 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400841 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530842 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000843 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530844 log.Fields{
845 "uni": uni,
846 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530847 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530848 }
Gamze Abakafee36392019-10-03 11:17:24 +0000849
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700851 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700852 if UsMeterID != 0 {
853 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
854 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
855 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700858 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700859 "onu-id": onuID,
860 "uni-id": uniID,
861 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700862 "meter-id": UsMeterID,
863 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000864 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700865 return 0, nil, nil
866 }
867 }
868 if DsMeterID != 0 {
869 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
870 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
871 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000872 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700873 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700874 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700875 "onu-id": onuID,
876 "uni-id": uniID,
877 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 "meter-id": DsMeterID,
879 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000880 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 return 0, nil, nil
882 }
883 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700884 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700885 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700886 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700888 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000889
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700890 if tpInstanceExists {
891 return allocID, gemPortIDs, techProfileInstance
892 }
893
894 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700895 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000897 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700899 "intf-id": intfID,
900 "onu-id": onuID,
901 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 "alloc-ids": allocIDs,
903 "gemports": allgemPortIDs,
904 "device-id": f.deviceHandler.device.Id})
905 // Send Tconts and GEM ports to KV store
906 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530907 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400908 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909 // CreateSchedulerQueues for EPON needs to be implemented here
910 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700911 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700912 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700913 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700914 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700915 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916
917 if tpInstanceExists {
918 return allocID, gemPortIDs, techProfileInstance
919 }
920
921 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700922 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700923 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700925 log.Fields{
926 "alloc-ids": allocIDs,
927 "gemports": allgemPortIDs,
928 "device-id": f.deviceHandler.device.Id})
929 // Send Tconts and GEM ports to KV store
930 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
931 return allocID, gemPortIDs, techProfileInstance
932 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700934 log.Fields{
935 "tpInst": tpInst})
936 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530937 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530938}
939
npujarec5762e2020-01-01 14:08:48 +0530940func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530941
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530943 log.Fields{
944 "intf-id": intfID,
945 "onu-id": onuID,
946 "uni-id": uniID,
947 "alloc-id": allocID,
948 "gemport-ids": gemPortIDs,
949 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530950 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000951 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000952 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 +0530953 }
yasin saplibddc2d72022-02-08 13:10:17 +0000954 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000955 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 +0530956 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700957
Neha Sharma96b7bf22020-06-15 10:37:32 +0000958 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 -0400959 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000960 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000961 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
962 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400963 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530964}
965
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700966func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530967 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000968 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700969 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
970 var err error
971 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
972 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
973 if err != nil || f.techprofile == nil {
974 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
975 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
976 }
977 logger.Debugw(ctx, "init-tech-profile-done",
978 log.Fields{
979 "intf-id": intfID,
980 "device-id": f.deviceHandler.device.Id})
981 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700982 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530983 }
984 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700985 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
986 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 +0530987}
988
Gamze Abaka7650be62021-02-26 10:50:36 +0000989func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800990 flowContext.classifier[PacketTagType] = SingleTag
991 // extract the cvid/inner-vid from the write metadata
992 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
993 if writeMetadata != 0 {
994 // Writemetadata field is 8 bytes
995 // cvid is on the outer most two bytes of the write metadata
996 cvid := (writeMetadata & 0xffff000000000000) >> 48
997 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
998 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
999 flowContext.classifier[PacketTagType] = DoubleTag
1000 }
1001 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001002 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301003 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001004 "uplinkClassifier": flowContext.classifier,
1005 "uplinkAction": flowContext.action})
1006 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301007}
1008
Gamze Abaka7650be62021-02-26 10:50:36 +00001009func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1010 downlinkClassifier := flowContext.classifier
1011 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001012 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1013 downlinkClassifier[PacketTagType] = SingleTag
1014 // extract the cvid/inner-vid from the write metadata
1015 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1016 if writeMetadata != 0 {
1017 // Writemetadata field is 8 bytes
1018 // cvid is on the outer most two bytes of the write metadata
1019 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1020 downlinkClassifier[PacketTagType] = DoubleTag
1021 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301022 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001023 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301024 log.Fields{
1025 "downlinkClassifier": downlinkClassifier,
1026 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001027
Girish Gowdraffa52e52022-02-16 15:48:10 -08001028 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1029 // The matched vlan is the one that is getting popped.
1030 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1031 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1032 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1033 if ok {
1034 downlinkAction[VlanVid] = dlClVid & 0xfff
1035 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301036 }
1037
Gamze Abaka7650be62021-02-26 10:50:36 +00001038 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301039}
1040
Gamze Abaka7650be62021-02-26 10:50:36 +00001041func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001042
Gamze Abaka7650be62021-02-26 10:50:36 +00001043 intfID := flowContext.intfID
1044 onuID := flowContext.onuID
1045 uniID := flowContext.uniID
1046 classifier := flowContext.classifier
1047 action := flowContext.action
1048 allocID := flowContext.allocID
1049 gemPortID := flowContext.gemPortID
1050 tpID := flowContext.tpID
1051 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001052 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301053 log.Fields{
1054 "intf-id": intfID,
1055 "onu-id": onuID,
1056 "uni-id": uniID,
1057 "device-id": f.deviceHandler.device.Id,
1058 "classifier": classifier,
1059 "action": action,
1060 "direction": direction,
1061 "alloc-id": allocID,
1062 "gemport-id": gemPortID,
1063 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001064
yasin saplibddc2d72022-02-08 13:10:17 +00001065 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001066 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001067 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301068 log.Fields{
1069 "device-id": f.deviceHandler.device.Id,
1070 "intf-id": intfID,
1071 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 return nil
yasin saplid0566272021-12-21 09:10:30 +00001073 } else if err != nil {
1074 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1075 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1076 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301077 }
yasin saplid0566272021-12-21 09:10:30 +00001078
David K. Bainbridge794735f2020-02-11 21:01:37 -08001079 classifierProto, err := makeOpenOltClassifierField(classifier)
1080 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301081 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301082 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001083 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301084 log.Fields{
1085 "classifier": *classifierProto,
1086 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001087 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001088 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301089 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301090 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001091 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301092 log.Fields{
1093 "action": *actionProto,
1094 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001095 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301096 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301097 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 log.Fields{
1099 "classifier": classifier,
1100 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301101 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301103 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001104
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001105 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001106 OnuId: int32(onuID),
1107 UniId: int32(uniID),
1108 FlowId: logicalFlow.Id,
1109 FlowType: direction,
1110 AllocId: int32(allocID),
1111 NetworkIntfId: int32(networkIntfID),
1112 GemportId: int32(gemPortID),
1113 Classifier: classifierProto,
1114 Action: actionProto,
1115 Priority: int32(logicalFlow.Priority),
1116 Cookie: logicalFlow.Cookie,
1117 PortNo: flowContext.portNo,
1118 TechProfileId: tpID,
1119 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1120 PbitToGemport: flowContext.pbitToGem,
1121 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001122 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001124 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301125 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001126 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301127 log.Fields{"direction": direction,
1128 "device-id": f.deviceHandler.device.Id,
1129 "flow": flow,
1130 "intf-id": intfID,
1131 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001132
David K. Bainbridge794735f2020-02-11 21:01:37 -08001133 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301134}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001135
Gamze Abaka7650be62021-02-26 10:50:36 +00001136func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1137
1138 intfID := flowContext.intfID
1139 onuID := flowContext.onuID
1140 uniID := flowContext.uniID
1141 logicalFlow := flowContext.logicalFlow
1142 classifier := flowContext.classifier
1143 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301144
Neha Sharma96b7bf22020-06-15 10:37:32 +00001145 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301146 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301147 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301149 "action": action,
1150 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001151 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301152 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
1154 // Clear the action map
1155 for k := range action {
1156 delete(action, k)
1157 }
1158
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001159 action[TrapToHost] = true
1160 classifier[UDPSrc] = uint32(68)
1161 classifier[UDPDst] = uint32(67)
1162 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301163
yasin saplibddc2d72022-02-08 13:10:17 +00001164 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001165 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001166 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301167 log.Fields{
1168 "device-id": f.deviceHandler.device.Id,
1169 "intf-id": intfID,
1170 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001171 return nil
yasin saplid0566272021-12-21 09:10:30 +00001172 } else if err != nil {
1173 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1174 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1175 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301176 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301177
Neha Sharma96b7bf22020-06-15 10:37:32 +00001178 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301179 log.Fields{
1180 "ul_classifier": classifier,
1181 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001182 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301183 "intf-id": intfID,
1184 "onu-id": onuID,
1185 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186
David K. Bainbridge794735f2020-02-11 21:01:37 -08001187 classifierProto, err := makeOpenOltClassifierField(classifier)
1188 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301189 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301190 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001191 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001192 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301194 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301195 }
1196
David K. Bainbridge794735f2020-02-11 21:01:37 -08001197 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001198 OnuId: int32(onuID),
1199 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001200 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001201 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001203 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001204 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301205 Classifier: classifierProto,
1206 Action: actionProto,
1207 Priority: int32(logicalFlow.Priority),
1208 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001209 PortNo: flowContext.portNo,
1210 TechProfileId: flowContext.tpID,
1211 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1212 PbitToGemport: flowContext.pbitToGem,
1213 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001214 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001216 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001218 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301219 log.Fields{
1220 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001221 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301222 "intf-id": intfID,
1223 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301224
David K. Bainbridge794735f2020-02-11 21:01:37 -08001225 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301226}
1227
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001228// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001229func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1230 delete(flowContext.classifier, VlanVid)
1231 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001232}
1233
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001234// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001235func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1236
1237 intfID := flowContext.intfID
1238 onuID := flowContext.onuID
1239 uniID := flowContext.uniID
1240 logicalFlow := flowContext.logicalFlow
1241 classifier := flowContext.classifier
1242 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001243
Neha Sharma96b7bf22020-06-15 10:37:32 +00001244 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301246 return olterrors.NewErrNotFound("nni-interface-id",
1247 log.Fields{
1248 "classifier": classifier,
1249 "action": action,
1250 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001252 }
1253
1254 // Clear the action map
1255 for k := range action {
1256 delete(action, k)
1257 }
1258
1259 action[TrapToHost] = true
1260 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261
yasin saplibddc2d72022-02-08 13:10:17 +00001262 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001263 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001264 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001265 return nil
yasin saplid0566272021-12-21 09:10:30 +00001266 } else if err != nil {
1267 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1268 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1269 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270 }
1271
Neha Sharma96b7bf22020-06-15 10:37:32 +00001272 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301273 log.Fields{
1274 "ul_classifier": classifier,
1275 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001276 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301277 "device-id": f.deviceHandler.device.Id,
1278 "intf-id": intfID,
1279 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001280
David K. Bainbridge794735f2020-02-11 21:01:37 -08001281 classifierProto, err := makeOpenOltClassifierField(classifier)
1282 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301283 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001284 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001285 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301286 log.Fields{
1287 "classifier": *classifierProto,
1288 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001289 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301291 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001292 }
1293
David K. Bainbridge794735f2020-02-11 21:01:37 -08001294 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 OnuId: int32(onuID),
1296 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001297 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001298 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001300 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001301 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001302 Classifier: classifierProto,
1303 Action: actionProto,
1304 Priority: int32(logicalFlow.Priority),
1305 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001306 PortNo: flowContext.portNo,
1307 TechProfileId: flowContext.tpID,
1308 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1309 PbitToGemport: flowContext.pbitToGem,
1310 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001311 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001312
David K. Bainbridge794735f2020-02-11 21:01:37 -08001313 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001314 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 -08001315 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001316
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001318}
1319
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001320// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001321func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1322 intfID := flowContext.intfID
1323 onuID := flowContext.onuID
1324 uniID := flowContext.uniID
1325 portNo := flowContext.portNo
1326 allocID := flowContext.allocID
1327 gemPortID := flowContext.gemPortID
1328 logicalFlow := flowContext.logicalFlow
1329 classifier := flowContext.classifier
1330 action := flowContext.action
1331
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001332 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301333 log.Fields{
1334 "intf-id": intfID,
1335 "onu-id": onuID,
1336 "port-no": portNo,
1337 "alloc-id": allocID,
1338 "gemport-id": gemPortID,
1339 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001340 "flow": logicalFlow,
1341 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301342
1343 uplinkClassifier := make(map[string]interface{})
1344 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301345
manikkaraj kbf256be2019-03-25 00:13:48 +05301346 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001347 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001348 uplinkClassifier[PacketTagType] = SingleTag
1349 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001350 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301351 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001352 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001353 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001354 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001355 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301356 "device-id": f.deviceHandler.device.Id,
1357 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001358 "intf-id": intfID,
1359 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001360 return nil
yasin saplid0566272021-12-21 09:10:30 +00001361 } else if err != nil {
1362 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1363 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1364 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301365 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001366 //Add Uplink EthType Flow
1367 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301368 log.Fields{
1369 "ul_classifier": uplinkClassifier,
1370 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001371 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301372 "device-id": f.deviceHandler.device.Id,
1373 "intf-id": intfID,
1374 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301375
David K. Bainbridge794735f2020-02-11 21:01:37 -08001376 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1377 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301378 return olterrors.NewErrInvalidValue(log.Fields{
1379 "classifier": uplinkClassifier,
1380 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301381 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001382 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301383 log.Fields{
1384 "classifier": *classifierProto,
1385 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001386 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001387 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301388 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301389 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001390 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301391 log.Fields{
1392 "action": *actionProto,
1393 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001394 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301395 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301396 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301398 "action": action,
1399 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301401 }
1402
David K. Bainbridge794735f2020-02-11 21:01:37 -08001403 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001404 OnuId: int32(onuID),
1405 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001406 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001407 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001408 AllocId: int32(allocID),
1409 NetworkIntfId: int32(networkIntfID),
1410 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301411 Classifier: classifierProto,
1412 Action: actionProto,
1413 Priority: int32(logicalFlow.Priority),
1414 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001415 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001416 TechProfileId: flowContext.tpID,
1417 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1418 PbitToGemport: flowContext.pbitToGem,
1419 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001420 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001422 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001424 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301425 log.Fields{
1426 "device-id": f.deviceHandler.device.Id,
1427 "onu-id": onuID,
1428 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001429 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301430 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001431
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301433}
1434
David K. Bainbridge794735f2020-02-11 21:01:37 -08001435func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001436 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001437
1438 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1439 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1440 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001441 if vlanID != ReservedVlan {
1442 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001443 classifier.OVid = vid
1444 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301445 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001446 // The classifierInfo[Metadata] is set for the following flows
1447 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1448 // - Mcast flow that points to a group in the treatment
1449 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1450 // - inner vid for a double tagged packet in the datapath flow
1451 // - outer vid for a single tagged packet in the datapath flow
1452 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001453 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1454 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301455 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1456 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1457 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1458 // becomes the IVid.
1459 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1460 if vid != ReservedVlan {
1461 classifier.IVid = vid
1462 }
1463 } else {
1464 if vid != ReservedVlan {
1465 classifier.OVid = vid
1466 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001467 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301469 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001470 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301471 classifier.OPbits = vlanPcp
1472 } else {
1473 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301474 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001475 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1476 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1477 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1478 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001479 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001480 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001481 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1482 classifier.PktTagType = pktTagType
1483
1484 switch pktTagType {
1485 case SingleTag:
1486 case DoubleTag:
1487 case Untagged:
1488 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001489 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301490 }
1491 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001492 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301493}
1494
Gamze Abaka724d0852020-03-18 12:10:24 +00001495func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001496 var actionCmd openoltpb2.ActionCmd
1497 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001500 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301501 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001502 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001503 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001504 action.Cmd.RemarkInnerPbits = true
1505 action.IPbits = actionInfo[VlanPcp].(uint32)
1506 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001507 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001508 action.Cmd.TranslateInnerTag = true
1509 action.IVid = actionInfo[VlanVid].(uint32)
1510 }
1511 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001512 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001513 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001514 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301515 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001516 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001517 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001518 action.OPbits = actionInfo[VlanPcp].(uint32)
1519 action.Cmd.RemarkOuterPbits = true
1520 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001521 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001522 action.IVid = classifierInfo[VlanVid].(uint32)
1523 action.Cmd.TranslateInnerTag = true
1524 }
1525 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001526 } else if _, ok := actionInfo[TrapToHost]; ok {
1527 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001528 } else if _, ok := actionInfo[VlanVid]; ok {
1529 // Translate outer vid
1530 action.Cmd.TranslateOuterTag = true
1531 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301532 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301533 // When OLT is transparent to vlans no-action is valid.
1534 /*
1535 else {
1536 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1537 }
1538 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001539 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301540}
1541
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001542// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001543func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001544 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301545}
1546
Gamze Abakafee36392019-10-03 11:17:24 +00001547// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001548// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1549// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1550// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1551// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1552// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1553// because it was observed that if the ONU device was deleted too soon after the flows were
1554// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1555// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1556// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001557func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001558 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001559 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1560
Gamze Abakafee36392019-10-03 11:17:24 +00001561 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001562
1563 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001564 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001565 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001566 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001567 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1568 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1569 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1570 log.Fields{
1571 "tp-id": tpID,
1572 "path": tpPath})
1573 }
1574 switch tpInstance := tpInst.(type) {
1575 case *tp_pb.TechProfileInstance:
1576 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1577 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1578 }
1579 // Force cleanup scheduler/queues -- end
1580
1581 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301582 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001583 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301584 // return err
1585 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001586 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001587 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 +00001588 }
1589 return nil
1590}
1591
1592// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301593func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001594 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001595 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001596 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001597 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301598 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1599 log.Fields{
1600 "tp-id": tpID,
1601 "uni-port-name": uniPortName,
1602 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001603 }
1604 return nil
1605}
1606
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001608
1609 var intfID uint32
1610 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1611 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1612 */
1613 if deviceFlow.AccessIntfId != -1 {
1614 intfID = uint32(deviceFlow.AccessIntfId)
1615 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001616 // We need to log the valid interface ID.
1617 // 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 +00001618 intfID = uint32(deviceFlow.NetworkIntfId)
1619 }
1620
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301622 "flow": *deviceFlow,
1623 "device-id": f.deviceHandler.device.Id,
1624 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001625 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001626
1627 st, _ := status.FromError(err)
1628 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001629 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001630 "err": err,
1631 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301632 "device-id": f.deviceHandler.device.Id,
1633 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001634 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301635 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001636
1637 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301639 log.Fields{"err": err,
1640 "device-flow": deviceFlow,
1641 "device-id": f.deviceHandler.device.Id,
1642 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001643 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001644 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301646 log.Fields{
1647 "flow": *deviceFlow,
1648 "device-id": f.deviceHandler.device.Id,
1649 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001650
yasin saplid0566272021-12-21 09:10:30 +00001651 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1652 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1653 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001654 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001655 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001656}
1657
Neha Sharma96b7bf22020-06-15 10:37:32 +00001658func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1659 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "flow": *deviceFlow,
1662 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001663 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001664 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001665 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001666 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301667 log.Fields{
1668 "err": err,
1669 "deviceFlow": deviceFlow,
1670 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001671 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001672 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001673 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001674 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001675
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001676 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001677 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001678 "of-flow-id": ofFlowID,
1679 "flow": *deviceFlow,
1680 "device-id": f.deviceHandler.device.Id,
1681 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001682 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301683}
1684
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001686
1687 classifierInfo := make(map[string]interface{})
1688 actionInfo := make(map[string]interface{})
1689
1690 classifierInfo[EthType] = uint32(LldpEthType)
1691 classifierInfo[PacketTagType] = Untagged
1692 actionInfo[TrapToHost] = true
1693
1694 // LLDP flow is installed to trap LLDP packets on the NNI port.
1695 // We manage flow_id resource pool on per PON port basis.
1696 // Since this situation is tricky, as a hack, we pass the NNI port
1697 // index (network_intf_id) as PON port Index for the flow_id resource
1698 // pool. Also, there is no ONU Id available for trapping LLDP packets
1699 // on NNI port, use onu_id as -1 (invalid)
1700 // ****************** CAVEAT *******************
1701 // This logic works if the NNI Port Id falls within the same valid
1702 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1703 // we need to have a re-look at this.
1704 // *********************************************
1705
1706 var onuID = -1
1707 var uniID = -1
1708 var gemPortID = -1
1709
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001710 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301712 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 }
yasin saplibddc2d72022-02-08 13:10:17 +00001714 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001715 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 return nil
yasin saplid0566272021-12-21 09:10:30 +00001718 } else if err != nil {
1719 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1720 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1721 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001722 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001723
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1725 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301726 return olterrors.NewErrInvalidValue(
1727 log.Fields{
1728 "classifier": classifierInfo,
1729 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001730 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001731 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301732 log.Fields{
1733 "classifier": *classifierProto,
1734 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001735 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301737 return olterrors.NewErrInvalidValue(
1738 log.Fields{
1739 "action": actionInfo,
1740 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301743 log.Fields{
1744 "action": *actionProto,
1745 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001746
1747 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1748 OnuId: int32(onuID), // OnuId not required
1749 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001750 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001751 FlowType: Downstream,
1752 NetworkIntfId: int32(networkInterfaceID),
1753 GemportId: int32(gemPortID),
1754 Classifier: classifierProto,
1755 Action: actionProto,
1756 Priority: int32(flow.Priority),
1757 Cookie: flow.Cookie,
1758 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001759 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001760 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "flow": downstreamflow,
1763 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001764 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "device-id": f.deviceHandler.device.Id,
1768 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001769 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001770
David K. Bainbridge794735f2020-02-11 21:01:37 -08001771 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301772}
1773
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001774func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1775 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001776}
1777
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001778// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001779func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001780 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1781 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1782 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001783 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301784 log.Fields{
1785 "intf-id": intfID,
1786 "onu-id": onuID,
1787 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001789 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301790 return nil, olterrors.NewErrNotFound("onu-child-device",
1791 log.Fields{
1792 "onu-id": onuID,
1793 "intf-id": intfID,
1794 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001795 }
khenaidoo106c61a2021-08-11 18:05:46 -04001796 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 -07001797 //better to ad the device to cache here.
1798 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1799 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001800 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301801 log.Fields{
1802 "intf-id": intfID,
1803 "onu-id": onuID,
1804 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001805 }
1806
1807 return onuDev.(*OnuDevice), nil
1808}
1809
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001810// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1812 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301813 log.Fields{
1814 "pon-port": intfID,
1815 "onu-id": onuID,
1816 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001817 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001818 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001819 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301820 return nil, olterrors.NewErrNotFound("onu",
1821 log.Fields{
1822 "interface-id": parentPortNo,
1823 "onu-id": onuID,
1824 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001825 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301826 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001827 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301828 log.Fields{
1829 "device-id": f.deviceHandler.device.Id,
1830 "child_device_id": onuDevice.Id,
1831 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301832 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301833}
1834
Neha Sharma96b7bf22020-06-15 10:37:32 +00001835func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1836 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301837 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "intf-id": intfID,
1841 "onu-id": onuID,
1842 "uni-id": uniID,
1843 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001844 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301845 }
1846
khenaidoodc2116e2021-10-19 17:33:19 -04001847 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001848 DeviceId: onuDev.deviceID,
1849 UniId: uniID,
1850 TpInstancePath: tpPath,
1851 GemPortId: gemPortID,
1852 }
1853 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1854
1855 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301856 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1857 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001858 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1859 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301860 "onu-id": onuDev.deviceID,
1861 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001862 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301863 }
khenaidoo106c61a2021-08-11 18:05:46 -04001864
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301866 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001867 "msg": delGemPortMsg,
1868 "from-adapter": f.deviceHandler.device.Type,
1869 "to-adapter": onuDev.deviceType,
1870 "device-id": f.deviceHandler.device.Id,
1871 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301872 return nil
1873}
1874
Neha Sharma96b7bf22020-06-15 10:37:32 +00001875func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1876 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301877 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001878 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301879 log.Fields{
1880 "intf-id": intfID,
1881 "onu-id": onuID,
1882 "uni-id": uniID,
1883 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001884 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 }
1886
khenaidoodc2116e2021-10-19 17:33:19 -04001887 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001888 DeviceId: onuDev.deviceID,
1889 UniId: uniID,
1890 TpInstancePath: tpPath,
1891 AllocId: allocID,
1892 }
1893
Neha Sharma96b7bf22020-06-15 10:37:32 +00001894 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301895 log.Fields{
1896 "msg": *delTcontMsg,
1897 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001898
1899 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301900 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1901 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001902 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1903 "to-adapter": onuDev.adapterEndpoint,
1904 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301905 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001906 "device-id": f.deviceHandler.device.Id}, err)
1907
Girish Gowdra6b130582019-11-20 16:45:20 +05301908 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001909 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301910 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001911 "msg": delTcontMsg,
1912 "device-id": f.deviceHandler.device.Id,
1913 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301914 return nil
1915}
1916
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001917// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001918// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001919func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001920 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001921
1922 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001923
Girish Gowdraa482f272021-03-24 23:04:19 -07001924 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001925 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1927 log.Fields{
1928 "tpPath": tpPath,
1929 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001930
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001931 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001932 if err != nil || techprofileInst == nil {
1933 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1934 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1935 if childDevice == nil {
1936 // happens when subscriber un-provision is immediately followed by child device delete
1937 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1938 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1939 return nil
1940 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001941 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1942 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001943 log.Fields{
1944 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001945 "path": tpPath}, err).Log()
1946 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001947 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001948
1949 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001950 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001951 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001952 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1953 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001954 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1955 if err != nil {
1956 return err
1957 }
1958 used := false
1959 for _, id := range flowIDs {
1960 if flowID != id {
1961 used = true
1962 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001963 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001964 }
1965 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001966 for i, flowIDinMap := range flowIDs {
1967 if flowIDinMap == flowID {
1968 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001969 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001970 return err
1971 }
1972 break
1973 }
1974 }
1975 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1976 log.Fields{
1977 "gemport-id": gemPortID,
1978 "usedByFlows": flowIDs,
1979 "currentFlow": flowID,
1980 "device-id": f.deviceHandler.device.Id})
1981 allGemPortsFree = false
1982 }
1983 }
1984 if !allGemPortsFree {
1985 return nil
1986 }
1987 }
1988
1989 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 -08001990
1991 // 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 +00001992 switch techprofileInst := techprofileInst.(type) {
1993 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001994 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1995 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001996 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001997
yasin saplibddc2d72022-02-08 13:10:17 +00001998 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001999 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2000 log.Fields{
2001 "err": err,
2002 "intf": intfID,
2003 "onu-id": onuID,
2004 "uni-id": uniID,
2005 "device-id": f.deviceHandler.device.Id,
2006 "gemport-id": gemPortID})
2007 }
2008
2009 }
2010 // Remove queues at OLT in upstream and downstream direction
2011 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2012 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2013 logger.Warn(ctx, err)
2014 }
2015 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2016 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2017 logger.Warn(ctx, err)
2018 }
2019 }
2020
2021 switch techprofileInst := techprofileInst.(type) {
2022 case *tp_pb.TechProfileInstance:
2023 // Proceed to free allocid and cleanup schedulers (US/DS) if no other references are found for this TP across all the UNIs on the ONU
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002024 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2025 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2026 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002027 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002028 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002029 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002030 logger.Warn(ctx, err)
2031 }
2032 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002033 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002034 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002035 } else {
2036 // just remove meter reference for the upstream direction for the current pon/onu/uni
2037 // The upstream scheduler, alloc id and meter-reference for the last remaining pon/onu/uni will be removed when no other alloc references that TP
2038 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2039 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002040 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002041 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2042 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002043 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002044 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002045
Girish Gowdraf3728b12022-02-02 21:46:51 -08002046 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2047 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002048 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002049 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2050 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002051 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002052 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002053 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002054 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002055 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002056 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302057 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002058 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302059 "onu-id": onuID,
2060 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002061 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002062 "alloc-id": techprofileInst.AllocId,
2063 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002064 }
yasin saplibddc2d72022-02-08 13:10:17 +00002065 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302066 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2067 logger.Warn(ctx, err)
2068 }
2069 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2070 logger.Warn(ctx, err)
2071 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002072 default:
2073 logger.Errorw(ctx, "error-unknown-tech",
2074 log.Fields{
2075 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002076 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002077
2078 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2079 switch techprofileInst := techprofileInst.(type) {
2080 case *tp_pb.TechProfileInstance:
2081 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2082 // Delete the gem port on the ONU.
2083 if sendDeleteGemRequest {
2084 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2085 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2086 log.Fields{
2087 "err": err,
2088 "intfID": intfID,
2089 "onu-id": onuID,
2090 "uni-id": uniID,
2091 "device-id": f.deviceHandler.device.Id,
2092 "gemport-id": gemPort.GemportId})
2093 }
yasin saplibddc2d72022-02-08 13:10:17 +00002094 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002095 }
2096 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302097 //Delete the tp instance and the techprofileid for onu at the end
2098 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2099 logger.Warn(ctx, err)
2100 }
2101 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2102 logger.Warn(ctx, err)
2103 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002104 }
2105
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302106 return nil
2107}
2108
David K. Bainbridge794735f2020-02-11 21:01:37 -08002109// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002110func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002111 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302112 log.Fields{
2113 "flowDirection": flowDirection,
2114 "flow": *flow,
2115 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002116
2117 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002118 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002119 }
2120
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302121 var ethType, ipProto, inPort uint32
2122 for _, field := range flows.GetOfbFields(flow) {
2123 if field.Type == flows.IP_PROTO {
2124 ipProto = field.GetIpProto()
2125 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2126 } else if field.Type == flows.ETH_TYPE {
2127 ethType = field.GetEthType()
2128 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2129 } else if field.Type == flows.IN_PORT {
2130 inPort = field.GetPort()
2131 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2132 }
2133 }
2134 portType := plt.IntfIDToPortTypeName(inPort)
2135 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2136 (portType == voltha.Port_ETHERNET_NNI) {
2137 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2138 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2139 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2140 // No more processing needed for trap from nni flows.
2141 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302142
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302143 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302144 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002145 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002146 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302147 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002148 onuID := int32(onu)
2149 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002150 tpID, err := getTpIDFromFlow(ctx, flow)
2151 if err != nil {
2152 return olterrors.NewErrNotFound("tp-id",
2153 log.Fields{
2154 "flow": flow,
2155 "intf-id": Intf,
2156 "onu-id": onuID,
2157 "uni-id": uniID,
2158 "device-id": f.deviceHandler.device.Id}, err)
2159 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302160
Neha Sharma96b7bf22020-06-15 10:37:32 +00002161 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302162 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002163 "flow-id": flow.Id,
2164 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302165 "onu-id": onuID,
2166 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302167
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002168 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2169 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002170 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2171 return err
2172 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002173
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002174 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002175 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2176 "flow-id": flow.Id,
2177 "device-id": f.deviceHandler.device.Id,
2178 "onu-id": onuID,
2179 "intf": Intf,
2180 "err": err,
2181 })
2182 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002184
Girish Gowdra82c80982021-03-26 16:22:02 -07002185 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +00002186 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002187 return err
2188 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002189 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002190}
2191
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002192// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002193func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002194
Matteo Scandolof16389e2021-05-18 00:47:08 +00002195 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302196 var direction string
2197 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002198
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302199 for _, action := range flows.GetActions(flow) {
2200 if action.Type == flows.OUTPUT {
2201 if out := action.GetOutput(); out != nil {
2202 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002203 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302204 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002205 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002206 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002207 }
2208 }
2209 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002210
2211 if flows.HasGroup(flow) {
2212 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002213 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002214 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302215 direction = Upstream
2216 } else {
2217 direction = Downstream
2218 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302219
Girish Gowdracefae192020-03-19 18:14:10 -07002220 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002221 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002222
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002223 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002224}
2225
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002226// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002227func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002228 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002229 if ethType, ok := classifierInfo[EthType]; ok {
2230 if ethType.(uint32) == IPv4EthType {
2231 if ipProto, ok := classifierInfo[IPProto]; ok {
2232 if ipProto.(uint32) == IgmpProto {
2233 return true
2234 }
2235 }
2236 }
2237 }
2238 }
2239 return false
2240}
2241
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002242// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002243func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002244 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2245 // The device itself is going to be reset as part of deletion. So nothing to be done.
2246 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2247 return nil
2248 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002249 // Step1 : Fill flowControlBlock
2250 // Step2 : Push the flowControlBlock to ONU channel
2251 // Step3 : Wait on response channel for response
2252 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002253 startTime := time.Now()
2254 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002255 errChan := make(chan error)
2256 flowCb := flowControlBlock{
2257 ctx: ctx,
2258 addFlow: addFlow,
2259 flow: flow,
2260 flowMetadata: flowMetadata,
2261 errChan: &errChan,
2262 }
2263 inPort, outPort := getPorts(flow)
2264 var onuID uint32
2265 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002266 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002267 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002268 if f.flowHandlerRoutineActive[onuID] {
2269 // inPort or outPort is InvalidPort for trap-from-nni flows.
2270 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2271 // Send the flowCb on the ONU flow channel
2272 f.incomingFlows[onuID] <- flowCb
2273 // Wait on the channel for flow handlers return value
2274 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002275 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002276 return err
2277 }
2278 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2279 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002280}
2281
2282// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2283// Each incoming flow is processed in a synchronous manner, i.e., the flow is processed to completion before picking another
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002284func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002285 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002286 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002287 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002288 // block on the channel to receive an incoming flow
2289 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002290 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002291 if flowCb.addFlow {
2292 logger.Info(flowCb.ctx, "adding-flow-start")
2293 startTime := time.Now()
2294 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2295 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2296 // Pass the return value over the return channel
2297 *flowCb.errChan <- err
2298 } else {
2299 logger.Info(flowCb.ctx, "removing-flow-start")
2300 startTime := time.Now()
2301 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2302 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2303 // Pass the return value over the return channel
2304 *flowCb.errChan <- err
2305 }
2306 case <-stopHandler:
2307 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2308 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002309 }
2310 }
2311}
2312
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002313// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002314func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002315 for i, v := range f.stopFlowHandlerRoutine {
2316 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002317 select {
2318 case v <- true:
2319 case <-time.After(time.Second * 5):
2320 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2321 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002322 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002323 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002324 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002325 f.stopFlowHandlerRoutine = nil
2326
2327 if f.incomingFlows != nil {
2328 for k := range f.incomingFlows {
2329 if f.incomingFlows[k] != nil {
2330 f.incomingFlows[k] = nil
2331 }
2332 }
2333 f.incomingFlows = nil
2334 }
2335
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002336 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002337 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2338}
2339
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002340// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302341// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002342func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002343 classifierInfo := make(map[string]interface{})
2344 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002345 var UsMeterID uint32
2346 var DsMeterID uint32
2347
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302349 log.Fields{
2350 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002351 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002353
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002355 if err != nil {
2356 // Error logging is already done in the called function
2357 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002358 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302359 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002360
Esin Karamanccb714b2019-11-29 15:02:06 +00002361 if flows.HasGroup(flow) {
2362 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002363 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002364 }
2365
manikkaraj k17652a72019-05-06 09:06:36 -04002366 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002367 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002368 if err != nil {
2369 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002370 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002371 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002372
Neha Sharma96b7bf22020-06-15 10:37:32 +00002373 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302374 log.Fields{
2375 "classifierinfo_inport": classifierInfo[InPort],
2376 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002377 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002378
Humera Kouser94d7a842019-08-25 19:04:32 -04002379 if ethType, ok := classifierInfo[EthType]; ok {
2380 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002381 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002382 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002383 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002384 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002385 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002386 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2387 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2388 }
2389 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002390 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002391 if ipProto, ok := classifierInfo[IPProto]; ok {
2392 if ipProto.(uint32) == IPProtoDhcp {
2393 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302394 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002395 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002396 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002397 }
2398 }
2399 }
2400 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002401 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002403 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002404 }
A R Karthick1f85b802019-10-11 05:06:05 +00002405
yasin saplibddc2d72022-02-08 13:10:17 +00002406 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002407
Girish Gowdra6071f382021-12-14 12:52:04 +05302408 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002409 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302410 return olterrors.NewErrNotFound("tpid-for-flow",
2411 log.Fields{
2412 "flow": flow,
2413 "intf-id": IntfID,
2414 "onu-id": onuID,
2415 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002416 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302418 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302419 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302420 "intf-id": intfID,
2421 "onu-id": onuID,
2422 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002423 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002424 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302426 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2427 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2428 return err
2429 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002430 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002431 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302433 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2434 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2435 return err
2436 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002437 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302438 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002439}
Girish Gowdra3d633032019-12-10 16:37:05 +05302440
Esin Karamanccb714b2019-11-29 15:02:06 +00002441// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302443 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302445 "classifier-info": classifierInfo,
2446 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002447
Esin Karaman65409d82020-03-18 10:58:18 +00002448 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002449 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002450 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002451 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002452
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002453 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002454
David K. Bainbridge794735f2020-02-11 21:01:37 -08002455 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002456
yasin saplibddc2d72022-02-08 13:10:17 +00002457 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002458 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002459 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002460 return nil
yasin saplid0566272021-12-21 09:10:30 +00002461 } else if err != nil {
2462 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2463 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2464 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002465 }
yasin saplid0566272021-12-21 09:10:30 +00002466
David K. Bainbridge794735f2020-02-11 21:01:37 -08002467 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2468 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002469 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002470 }
2471 groupID := actionInfo[GroupID].(uint32)
2472 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002473 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002474 FlowType: Multicast,
2475 NetworkIntfId: int32(networkInterfaceID),
2476 GroupId: groupID,
2477 Classifier: classifierProto,
2478 Priority: int32(flow.Priority),
2479 Cookie: flow.Cookie}
2480
Kent Hagermane6ff1012020-07-14 15:07:53 -04002481 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002482 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002485 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002486 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002487 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002488 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002489 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002490 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002491 //cached group can be removed now
2492 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002493 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002494 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002495 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002496
David K. Bainbridge794735f2020-02-11 21:01:37 -08002497 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002498}
2499
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002500// getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
Esin Karaman65409d82020-03-18 10:58:18 +00002501func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2502 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002503 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002504 if err != nil {
2505 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2506 }
2507 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002508 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002509
2510 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2511 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002512}
2513
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002514// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002515func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32, tpInst tp_pb.TechProfileInstance) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002516
Neha Sharma96b7bf22020-06-15 10:37:32 +00002517 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302518 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002519 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302520 log.Fields{
2521 "intf-id": intfID,
2522 "onu-id": onuID,
2523 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002524 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002527
yasin saplibddc2d72022-02-08 13:10:17 +00002528 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002529 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002530 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002531 UniId: uniID,
2532 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002533 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002534 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002535 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002536
2537 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2538 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302539 return olterrors.NewErrCommunication("send-techprofile-download-request",
2540 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002541 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302542 "to-adapter": onuDev.deviceType,
2543 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002544 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002545 }
nikesh.krishnan81ec7442023-10-31 17:19:34 +05302546 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302547 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302548}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002550// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302551func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002553
2554 if packetIn.IntfType == "pon" {
2555 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002556 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002557 onuID, uniID := packetIn.OnuId, packetIn.UniId
2558 logger.Debugf(ctx, "retrieved ONU and UNI IDs [%d, %d] by interface:%d, gem:%d", packetIn.OnuId, packetIn.UniId, packetIn.GemportId)
Esin Karamandf392e12020-12-16 13:33:09 +00002559
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002560 if packetIn.PortNo != 0 {
2561 logicalPortNum = packetIn.PortNo
2562 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002563 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002564 }
2565 // Store the gem port through which the packet_in came. Use the same gem port for packet_out
Esin Karaman7fb80c22020-07-16 14:23:33 +00002566 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002567 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002568 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002569 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002570
2571 if logger.V(log.DebugLevel) {
2572 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2573 log.Fields{
2574 "logical-port-num": logicalPortNum,
2575 "intf-type": packetIn.IntfType,
2576 "packet": hex.EncodeToString(packetIn.Pkt),
2577 })
2578 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579 return logicalPortNum, nil
2580}
2581
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002582// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002583func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002584 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002585
2586 ctag, priority, err := getCTagFromPacket(ctx, packet)
2587 if err != nil {
2588 return 0, err
2589 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302590
Esin Karaman7fb80c22020-07-16 14:23:33 +00002591 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002592 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002593 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002594 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002595 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302596 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002597 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302598 log.Fields{
2599 "pktinkey": pktInkey,
2600 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002601
2602 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302604 //If gem is not found in cache try to get it from kv store, if found in kv store, update the cache and return.
Esin Karaman7fb80c22020-07-16 14:23:33 +00002605 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302606 if err == nil {
2607 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002608 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302609 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002610 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002611 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302612 log.Fields{
2613 "pktinkey": pktInkey,
2614 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302615 return gemPortID, nil
2616 }
2617 }
Shrey Baid26912972020-04-16 21:02:31 +05302618 return uint32(0), olterrors.NewErrNotFound("gem-port",
2619 log.Fields{
2620 "pktinkey": pktInkey,
2621 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002622
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002623}
2624
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002625func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2626 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002627 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002628 classifier[PacketTagType] = DoubleTag
2629 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002630 /* We manage flowId resource pool on per PON port basis.
2631 Since this situation is tricky, as a hack, we pass the NNI port
2632 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002633 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634 on NNI port, use onu_id as -1 (invalid)
2635 ****************** CAVEAT *******************
2636 This logic works if the NNI Port Id falls within the same valid
2637 range of PON Port Ids. If this doesn't work for some OLT Vendor
2638 we need to have a re-look at this.
2639 *********************************************
2640 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002641 onuID := -1
2642 uniID := -1
2643 gemPortID := -1
2644 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002645 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302646 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302647 return olterrors.NewErrNotFound("nni-intreface-id",
2648 log.Fields{
2649 "classifier": classifier,
2650 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002651 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302652 }
2653
yasin saplibddc2d72022-02-08 13:10:17 +00002654 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002655 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002656 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002657 return nil
yasin saplid0566272021-12-21 09:10:30 +00002658 } else if err != nil {
2659 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2660 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2661 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002662 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002664 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2665 log.Fields{
2666 "classifier": classifier,
2667 "action": action,
2668 "flowId": logicalFlow.Id,
2669 "intf-id": networkInterfaceID})
2670
David K. Bainbridge794735f2020-02-11 21:01:37 -08002671 classifierProto, err := makeOpenOltClassifierField(classifier)
2672 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002673 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002675 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002676 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002677 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002678 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002680 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002681 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2682 OnuId: int32(onuID), // OnuId not required
2683 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002684 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002685 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002686 AllocId: int32(allocID), // AllocId not used
2687 NetworkIntfId: int32(networkInterfaceID),
2688 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002689 Classifier: classifierProto,
2690 Action: actionProto,
2691 Priority: int32(logicalFlow.Priority),
2692 Cookie: logicalFlow.Cookie,
2693 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002694 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002695 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002696 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002697 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002698 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002699}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002700
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002701// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002702func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2703 var packetType string
2704 ovid, ivid := false, false
2705 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2706 vid := vlanID & VlanvIDMask
2707 if vid != ReservedVlan {
2708 ovid = true
2709 }
2710 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002711
2712 // The classifierInfo[Metadata] is set for the following flows
2713 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2714 // - Mcast flow that points to a group in the action/treatment
2715 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2716 // - inner vid for a double tagged packet in the datapath flow
2717 // - outer vid for a single tagged packet in the datapath flow
2718 // - inner vid in the mcast flow that points to a group
2719
2720 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2721 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2722 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2723 // it is to be used with caution elsewhere as it could result in wrong packetType to be returned to the caller.
Esin Karamanae41e2b2019-12-17 18:13:13 +00002724 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2725 vid := uint32(metadata)
2726 if vid != ReservedVlan {
2727 ivid = true
2728 }
2729 }
2730 if ovid && ivid {
2731 packetType = DoubleTag
2732 } else if !ovid && !ivid {
2733 packetType = Untagged
2734 } else {
2735 packetType = SingleTag
2736 }
2737 return packetType
2738}
2739
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002740// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002741func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002742 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002743 action := make(map[string]interface{})
2744 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2745 action[TrapToHost] = true
2746 /* We manage flowId resource pool on per PON port basis.
2747 Since this situation is tricky, as a hack, we pass the NNI port
2748 index (network_intf_id) as PON port Index for the flowId resource
2749 pool. Also, there is no ONU Id available for trapping packets
2750 on NNI port, use onu_id as -1 (invalid)
2751 ****************** CAVEAT *******************
2752 This logic works if the NNI Port Id falls within the same valid
2753 range of PON Port Ids. If this doesn't work for some OLT Vendor
2754 we need to have a re-look at this.
2755 *********************************************
2756 */
2757 onuID := -1
2758 uniID := -1
2759 gemPortID := -1
2760 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002761 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002762 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302763 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002764 "classifier": classifier,
2765 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002766 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002767 }
yasin saplibddc2d72022-02-08 13:10:17 +00002768 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002769 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002770 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002771 return nil
yasin saplid0566272021-12-21 09:10:30 +00002772 } else if err != nil {
2773 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2774 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2775 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002776 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002777
David K. Bainbridge794735f2020-02-11 21:01:37 -08002778 classifierProto, err := makeOpenOltClassifierField(classifier)
2779 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002780 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002781 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002783 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002784 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002785 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002786 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002787 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2789 OnuId: int32(onuID), // OnuId not required
2790 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002791 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002792 FlowType: Downstream,
2793 AllocId: int32(allocID), // AllocId not used
2794 NetworkIntfId: int32(networkInterfaceID),
2795 GemportId: int32(gemPortID), // GemportId not used
2796 Classifier: classifierProto,
2797 Action: actionProto,
2798 Priority: int32(logicalFlow.Priority),
2799 Cookie: logicalFlow.Cookie,
2800 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002801 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002802 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002804 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002805
David K. Bainbridge794735f2020-02-11 21:01:37 -08002806 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002807}
2808
salmansiddiqui7ac62132019-08-22 03:58:50 +00002809func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2810 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302811 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002812 }
2813 if Dir == tp_pb.Direction_UPSTREAM {
2814 return "upstream", nil
2815 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2816 return "downstream", nil
2817 }
2818 return "", nil
2819}
2820
Kent Hagermane6ff1012020-07-14 15:07:53 -04002821// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302822func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002823 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002824 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002825 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002826 intfID := args[IntfID]
2827 onuID := args[OnuID]
2828 uniID := args[UniID]
2829 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002830 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002831 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002832 gemToAes := make(map[uint32]bool)
2833
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002834 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002835 var direction = tp_pb.Direction_UPSTREAM
2836 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002837 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002838 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002839 attributes = TpInst.UpstreamGemPortAttributeList
2840 } else {
2841 attributes = TpInst.DownstreamGemPortAttributeList
2842 direction = tp_pb.Direction_DOWNSTREAM
2843 }
2844 default:
2845 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002846 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848
2849 if len(gemPorts) == 1 {
2850 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002851 gemPortID = gemPorts[0]
2852 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002853 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2854 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002855 pBitMap := attributes[idx].PbitMap
2856 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2857 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2858 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002859 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002860 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2861 if pbitSet == pbit1 {
2862 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2863 pbitToGem[pcp] = gemID
2864 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002865 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002866 }
2867 }
2868 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002869 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2870 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2871 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 }
2874
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2876 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2877
salmansiddiqui7ac62132019-08-22 03:58:50 +00002878 if ipProto, ok := classifierInfo[IPProto]; ok {
2879 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002880 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002881 "tp-id": tpID,
2882 "alloc-id": allocID,
2883 "intf-id": intfID,
2884 "onu-id": onuID,
2885 "uni-id": uniID,
2886 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002887 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002888 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002889 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002890 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2891 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002892 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002893 }
2894
Girish Gowdra32625212020-04-29 11:26:35 -07002895 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302897 log.Fields{
2898 "intf-id": intfID,
2899 "onu-id": onuID,
2900 "uni-id": uniID,
2901 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002903 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002904 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2905 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002906 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002907 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002908 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002910 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002911 }
2912 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002913 if ethType.(uint32) == EapEthType {
2914 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002915 "intf-id": intfID,
2916 "onu-id": onuID,
2917 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002918 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002919 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 var vlanID uint32
2921 if val, ok := classifierInfo[VlanVid]; ok {
2922 vlanID = (val.(uint32)) & VlanvIDMask
2923 } else {
2924 vlanID = DefaultMgmtVlan
2925 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002926 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002927 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002928 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2929 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002930 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002931 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002932 } else if ethType.(uint32) == PPPoEDEthType {
2933 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2934 "tp-id": tpID,
2935 "alloc-id": allocID,
2936 "intf-id": intfID,
2937 "onu-id": onuID,
2938 "uni-id": uniID,
2939 })
2940 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002941 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002942 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002943 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2944 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002945 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002946 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002947 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002948 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002950 "intf-id": intfID,
2951 "onu-id": onuID,
2952 "uni-id": uniID,
2953 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002954 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002955 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002956 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002957 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2958 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002959 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002960 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002961 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002962 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002963 "intf-id": intfID,
2964 "onu-id": onuID,
2965 "uni-id": uniID,
2966 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002967 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002968 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002969 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002970 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2971 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002972 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 }
2974 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002975 return olterrors.NewErrInvalidValue(log.Fields{
2976 "intf-id": intfID,
2977 "onu-id": onuID,
2978 "uni-id": uniID,
2979 "classifier": classifierInfo,
2980 "action": actionInfo,
2981 "flow": flow},
2982 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002983 }
2984 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002985 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002986 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002987 logger.Warn(ctx, err)
2988 }
2989 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002990 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991}
2992
Gamze Abakacb0e6772021-06-10 08:32:12 +00002993func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002994 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2995 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2996 tpInstances := f.techprofile.FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp_pb.TechProfileInstance)
Girish Gowdra54934262019-11-13 14:19:55 +05302997 for i := 0; i < len(tpInstances); i++ {
2998 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002999 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003000 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003001 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003002 log.Fields{
3003 "device-id": f.deviceHandler.device.Id,
3004 "intfID": sq.intfID,
3005 "onuID": sq.onuID,
3006 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003007 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003008 })
3009 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303010 }
3011 }
3012 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003013 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003014}
3015
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003017 for _, field := range flows.GetOfbFields(flow) {
3018 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003020 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003021 } else if field.Type == flows.ETH_DST {
3022 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003023 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
3024 } else if field.Type == flows.ETH_SRC {
3025 classifierInfo[EthSrc] = field.GetEthSrc()
3026 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003027 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003028 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003030 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003031 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003033 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303034 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3035 if field.GetVlanVid() != ReservedVlan {
3036 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3037 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3038 }
Scott Baker355d1742019-10-24 10:57:52 -07003039 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003040 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003041 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003042 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003045 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003054 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003055 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003060 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 return
3063 }
3064 }
3065}
3066
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003068 for _, action := range flows.GetActions(flow) {
3069 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003070 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003071 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003074 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 }
Scott Baker355d1742019-10-24 10:57:52 -07003076 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003077 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003079 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 if out := action.GetPush(); out != nil {
3081 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 } else {
3084 actionInfo[PushVlan] = true
3085 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303087 log.Fields{
3088 "push-tpid": actionInfo[TPID].(uint32),
3089 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 }
3091 }
Scott Baker355d1742019-10-24 10:57:52 -07003092 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 if out := action.GetSetField(); out != nil {
3094 if field := out.GetField(); field != nil {
3095 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003096 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003097 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3099 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003100 }
3101 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003102 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003105 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003106 }
3107 }
3108 return nil
3109}
3110
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003112 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003113 fieldtype := ofbField.GetType()
3114 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003115 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3116 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003118 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003120 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003121 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3122 pcp := ofbField.GetVlanPcp()
3123 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003124 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003125 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003127 }
3128 }
3129}
3130
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003132 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003134 } else {
3135 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003136 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003137 }
3138}
3139
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003141 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003143 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003144 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003145 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303148 log.Fields{
3149 "newinport": classifierInfo[InPort].(uint32),
3150 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303152 return olterrors.NewErrNotFound("child-in-port",
3153 log.Fields{
3154 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3155 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003156 }
3157 }
3158 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003159 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003160 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003161 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003162 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003163 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003164 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303165 log.Fields{
3166 "newoutport": actionInfo[Output].(uint32),
3167 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003168 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303169 return olterrors.NewErrNotFound("out-port",
3170 log.Fields{
3171 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3172 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003173 }
3174 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003175 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003176 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003177 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303179 log.Fields{
3180 "newinport": actionInfo[Output].(uint32),
3181 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003182 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303183 return olterrors.NewErrNotFound("nni-port",
3184 log.Fields{
3185 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3186 "in-port": classifierInfo[InPort].(uint32),
3187 "out-port": actionInfo[Output].(uint32),
3188 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003189 }
3190 }
3191 }
3192 return nil
3193}
Gamze Abakafee36392019-10-03 11:17:24 +00003194
Neha Sharma96b7bf22020-06-15 10:37:32 +00003195func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003196 /* Metadata 8 bytes:
3197 Most Significant 2 Bytes = Inner VLAN
3198 Next 2 Bytes = Tech Profile ID(TPID)
3199 Least Significant 4 Bytes = Port ID
3200 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3201 subscriber related flows.
3202 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003203 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003204 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003205 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003206 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003207 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003208 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003209}
3210
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003211func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003212 for _, sliceElement := range slice {
3213 if sliceElement == item {
3214 return slice
3215 }
3216 }
3217 return append(slice, item)
3218}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303219
yasin saplie87d4bd2021-12-06 09:04:03 +00003220func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3221 for _, sliceElement := range slice {
3222 if sliceElement == item {
3223 return slice
3224 }
3225 }
3226 return append(slice, item)
3227}
3228
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303229// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003230func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303231
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003232 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303233 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003234 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003235 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003236 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003237 log.Fields{
3238 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003239 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003240 return uint32(0), err
3241 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003242 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303243 return intfID, nil
3244 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003245 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003246 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003248 log.Fields{
3249 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003250 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003251 return uint32(0), err
3252 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003253 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303254 return intfID, nil
3255 }
3256 return uint32(0), nil
3257}
3258
3259// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003260func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3261 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3262 if err != nil {
3263 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3264 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3265 return
3266 }
3267 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003268
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003269 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003270 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003271 f.packetInGemPortLock.RUnlock()
3272
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303273 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003274 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003275 logger.Infow(ctx, "pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
Shrey Baid26912972020-04-16 21:02:31 +05303276 log.Fields{
3277 "pktinkey": pktInkey,
3278 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003279 return
3280 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303281 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003282 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003283 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003284 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003285
npujarec5762e2020-01-01 14:08:48 +05303286 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003287 logger.Infow(ctx, "pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05303288 log.Fields{
3289 "pktinkey": pktInkey,
3290 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303291}
3292
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003293// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003294func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3295 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003296 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003297 return 0, 0, errors.New("invalid packet length")
3298 }
3299 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3300 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3301
3302 var index int8
3303 if outerEthType == 0x8100 {
3304 if innerEthType == 0x8100 {
3305 // q-in-q 802.1ad or 802.1q double tagged packet.
3306 // get the inner vlanId
3307 index = 18
3308 } else {
3309 index = 14
3310 }
3311 priority := (packet[index] >> 5) & 0x7
3312 //13 bits composes vlanId value
3313 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3314 return vlan, priority, nil
3315 }
3316 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3317 return 0, 0, nil
3318}
3319
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003320// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003321// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003322func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003323 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003324 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3325 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003326 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003327 "flow-id": flow.Id,
3328 "device-id": f.deviceHandler.device.Id})
3329 // Remove from device
3330 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3331 // DKB
3332 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3333 log.Fields{
3334 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003335 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003336 return err
3337 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003338
3339 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003340}
3341
khenaidoodc2116e2021-10-19 17:33:19 -04003342func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003343 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003344 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003345 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003346 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003347 }
3348
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003349 switch tpInst := tpInst.(type) {
3350 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003351 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003352 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003353 DeviceId: onuDeviceID,
3354 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003355 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003356 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003357 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003358 case *tp_pb.EponTechProfileInstance:
3359 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003360 DeviceId: onuDeviceID,
3361 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003362 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003363 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003364 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003365 default:
3366 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 }
khenaidoodc2116e2021-10-19 17:33:19 -04003368 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003369 DeviceId: onuDeviceID,
3370 UniId: uniID,
3371 TpInstancePath: tpPath,
3372 TechTpInstance: nil,
3373 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003374}
3375
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003376// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3377func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3378
3379 intfID := sq.intfID
3380 onuID := sq.onuID
3381 uniID := sq.uniID
3382 tpID := sq.tpID
3383
3384 var reverseDirection string
3385 if sq.direction == tp_pb.Direction_UPSTREAM {
3386 reverseDirection = "downstream"
3387 } else {
3388 reverseDirection = "upstream"
3389 }
3390
3391 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003392 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003393 return
3394 }
3395
3396 // revert-delete tech-profile instance and delete tech profile id for onu
3397 logger.Warnw(ctx, "reverting-tech-profile-instance-and-tech-profile-id-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "tp-id": tpID})
3398 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3399 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003400 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003401
3402 // free gem/alloc
3403 switch techprofileInst := sq.tpInst.(type) {
3404 case *tp_pb.TechProfileInstance:
3405 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003406 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003407 }
yasin saplibddc2d72022-02-08 13:10:17 +00003408 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003409 }
3410}
3411
3412// revertSchduler is called when CreateQueues request fails
3413func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3414 // revert scheduler
3415 logger.Warnw(ctx, "reverting-scheduler-for-onu", log.Fields{"intf-id": sq.intfID, "onu-id": sq.onuID, "uni-id": sq.uniID, "tp-id": sq.tpID})
3416 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3417 IntfId: sq.intfID, OnuId: sq.onuID,
3418 UniId: sq.uniID, PortNo: sq.uniPort,
3419 TrafficScheds: TrafficSched})
3420}
Girish Gowdra6071f382021-12-14 12:52:04 +05303421
3422// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3423func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00003424 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303425 if err != nil {
3426 return olterrors.NewErrNotFound("meter",
3427 log.Fields{"intf-id": intfID,
3428 "onu-id": onuID,
3429 "uni-id": uniID,
3430 "device-id": f.deviceHandler.device.Id}, err)
3431 }
3432
3433 if meterInfo != nil {
3434 // If RefCnt become 0 clear the meter information from the DB.
3435 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003436 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303437 return err
3438 }
3439 } else if meterInfo.MeterID != meterID {
3440 logger.Errorw(ctx, "meter-mismatch-for-direction",
3441 log.Fields{"direction": direction,
3442 "kv-store-meter-id": meterInfo.MeterID,
3443 "meter-id-in-flow": meterID,
3444 "device-id": f.deviceHandler.device.Id})
3445 return olterrors.NewErrInvalidValue(log.Fields{
3446 "unsupported": "meter-id",
3447 "kv-store-meter-id": meterInfo.MeterID,
3448 "meter-id-in-flow": meterID,
3449 "device-id": f.deviceHandler.device.Id}, nil)
3450 }
3451 }
3452 return nil
3453}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003454
3455func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3456 /* After we successfully remove the scheduler configuration on the OLT device,
3457 * delete the meter id on the KV store.
3458 */
yasin saplibddc2d72022-02-08 13:10:17 +00003459 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003460 if err != nil {
3461 return olterrors.NewErrAdapter("unable-to-remove-meter",
3462 log.Fields{
3463 "onu": sq.onuID,
3464 "device-id": f.deviceHandler.device.Id,
3465 "intf-id": sq.intfID,
3466 "onu-id": sq.onuID,
3467 "uni-id": sq.uniID,
3468 "uni-port": sq.uniPort}, err)
3469 }
3470 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3471 log.Fields{
3472 "dir": direction,
3473 "device-id": f.deviceHandler.device.Id,
3474 "intf-id": sq.intfID,
3475 "onu-id": sq.onuID,
3476 "uni-id": sq.uniID,
3477 "uni-port": sq.uniPort})
3478 return err
3479}