blob: 06ad2c0d3f128d5746665d799f728c2f684badbd [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdraffa52e52022-02-16 15:48:10 -080094 //EthSrc constant
95 EthSrc = "eth_src"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 //TPID constant
97 TPID = "tpid"
98 //IPProto constant
99 IPProto = "ip_proto"
100 //InPort constant
101 InPort = "in_port"
102 //VlanVid constant
103 VlanVid = "vlan_vid"
104 //VlanPcp constant
105 VlanPcp = "vlan_pcp"
106
107 //UDPDst constant
108 UDPDst = "udp_dst"
109 //UDPSrc constant
110 UDPSrc = "udp_src"
111 //Ipv4Dst constant
112 Ipv4Dst = "ipv4_dst"
113 //Ipv4Src constant
114 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700115 //Metadata constant
116 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 //TunnelID constant
118 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700119 //Output constant
120 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000121 //GroupID constant
122 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
125 //PopVlan constant
126 PopVlan = "pop_vlan"
127 //PushVlan constant
128 PushVlan = "push_vlan"
129 //TrapToHost constant
130 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400131 //MaxMeterBand constant
132 MaxMeterBand = 2
133 //VlanPCPMask contant
134 VlanPCPMask = 0xFF
135 //VlanvIDMask constant
136 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000137 //IntfID constant
138 IntfID = "intfId"
139 //OnuID constant
140 OnuID = "onuId"
141 //UniID constant
142 UniID = "uniId"
143 //PortNo constant
144 PortNo = "portNo"
145 //AllocID constant
146 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000147 //GemID constant
148 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000149
150 //NoneOnuID constant
151 NoneOnuID = -1
152 //NoneUniID constant
153 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700154
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700155 // Max number of flows that can be queued per ONU
156 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530157
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700158 bitMapPrefix = "0b"
159 pbit1 = '1'
160)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
163 direction tp_pb.Direction
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 tpID uint32
168 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700169 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000170 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400171 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 portNo uint32
179 classifier map[string]interface{}
180 action map[string]interface{}
181 logicalFlow *ofp.OfpFlowStats
182 allocID uint32
183 gemPortID uint32
184 tpID uint32
185 pbitToGem map[uint32]uint32
186 gemToAes map[uint32]bool
187}
188
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700189// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
190// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
191// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
192// flow and processes it serially
193type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400194 ctx context.Context // Flow handler context
195 addFlow bool // if true flow to be added, else removed
196 flow *ofp.OfpFlowStats // Flow message
197 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
198 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000199}
200
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530202type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700204 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700205 deviceHandler *DeviceHandler
206 grpMgr *OpenOltGroupMgr
207 resourceMgr *rsrcMgr.OpenOltResourceMgr
208
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700212 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
213 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700214 incomingFlows []chan flowControlBlock
215 stopFlowHandlerRoutine []chan bool
216 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530217}
218
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700220func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000221 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530222 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530223 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530224
manikkaraj kbf256be2019-03-25 00:13:48 +0530225 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700226 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700227 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530228 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000229 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
230 if ponPortIdx != dh.totalPonPorts {
231 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
232 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
233 return nil
234 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700237
238 // Create a slice of buffered channels for handling concurrent flows per ONU.
239 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700240 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
241 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
242 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700243 for i := range flowMgr.incomingFlows {
244 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800245 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246 // Spin up a go routine to handling incoming flows (add/remove).
247 // There will be on go routine per ONU.
248 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700249 flowMgr.flowHandlerRoutineActive[i] = true
250 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700252
Esin Karamanccb714b2019-11-29 15:02:06 +0000253 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700254 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000255 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530256 return &flowMgr
257}
258
Kent Hagermane6ff1012020-07-14 15:07:53 -0400259func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000260 // In case of nni trap flow
261 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000262 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
265 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin saplibddc2d72022-02-08 13:10:17 +0000266 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700267 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
268 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
269 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000270 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700271 return err
272 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700273 }
Gamze Abakafee36392019-10-03 11:17:24 +0000274 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 return nil
276}
277
Girish Gowdra9602eb42020-09-09 15:50:39 -0700278func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000279 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400280 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000281 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530282 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700283 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530284
Neha Sharma96b7bf22020-06-15 10:37:32 +0000285 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530286 "device-id": f.deviceHandler.device.Id,
287 "intf-id": intfID,
288 "onu-id": onuID,
289 "uni-id": uniID,
290 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700291 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530292 "action": actionInfo,
293 "usmeter-iD": UsMeterID,
294 "dsmeter-iD": DsMeterID,
295 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400296 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
297 // is because the flow is an NNI flow and there would be no onu resources associated with it
298 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400299 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200300 cause := "no-onu-id-for-flow"
301 fields := log.Fields{
302 "onu": onuID,
303 "port-no": portNo,
304 "classifer": classifierInfo,
305 "action": actionInfo,
306 "device-id": f.deviceHandler.device.Id}
307 logger.Errorw(ctx, cause, fields)
308 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530309 }
310
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700311 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530313 "uni": uni,
314 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530315
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700316 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
317 "device-id": f.deviceHandler.device.Id,
318 "intf-id": intfID,
319 "onu-id": onuID,
320 "uni-id": uniID,
321 "port-no": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo,
324 "usmeter-id": UsMeterID,
325 "dsmeter-id": DsMeterID,
326 "tp-id": TpID})
327 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
328 if allocID == 0 || gemPorts == nil || TpInst == nil {
329 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
330 return olterrors.NewErrNotFound(
331 "alloc-id-gem-ports-tp-unavailable",
332 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700334 args := make(map[string]uint32)
335 args[IntfID] = intfID
336 args[OnuID] = onuID
337 args[UniID] = uniID
338 args[PortNo] = portNo
339 args[AllocID] = allocID
340
341 /* Flows can be added specific to gemport if p-bits are received.
342 * If no pbit mentioned then adding flows for all gemports
343 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000344 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345}
346
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800348// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530349func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400350
Girish Gowdraf3728b12022-02-02 21:46:51 -0800351 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530352 log.Fields{"dir": sq.direction,
353 "intf-id": sq.intfID,
354 "onu-id": sq.onuID,
355 "uni-id": sq.uniID,
356 "tp-id": sq.tpID,
357 "meter-id": sq.meterID,
358 "tp-inst": sq.tpInst,
359 "flowmetadata": sq.flowMetadata,
360 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361
Girish Gowdra6071f382021-12-14 12:52:04 +0530362 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000363 if err != nil {
364 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 }
366
Girish Gowdraf3728b12022-02-02 21:46:51 -0800367 var TrafficShaping *tp_pb.TrafficShapingInfo
368 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
369 return olterrors.NewErrInvalidValue(log.Fields{
370 "reason": "invalid-meter-config",
371 "meter-id": sq.meterID,
372 "device-id": f.deviceHandler.device.Id}, nil)
373 }
374
375 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
376 return olterrors.NewErrInvalidValue(log.Fields{
377 "reason": "invalid-meter-config",
378 "meter-id": sq.meterID,
379 "device-id": f.deviceHandler.device.Id}, nil)
380 }
381
382 var SchedCfg *tp_pb.SchedulerConfig
383 if sq.direction == tp_pb.Direction_UPSTREAM {
384 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
385 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
386 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
387 }
388 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
389 TrafficSched[0].TechProfileId = sq.tpID
390
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 /* Lets make a simple assumption that if the meter-id is present on the KV store,
392 * then the scheduler and queues configuration is applied on the OLT device
393 * in the given direction.
394 */
yasin saplibddc2d72022-02-08 13:10:17 +0000395 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530397 return olterrors.NewErrNotFound("meter",
398 log.Fields{"intf-id": sq.intfID,
399 "onu-id": sq.onuID,
400 "uni-id": sq.uniID,
401 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000403
Girish Gowdraf3728b12022-02-02 21:46:51 -0800404 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530405 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800406 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530407 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000408 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800409 return err
410 }
411
412 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
413 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
414 // Just create gem ports and traffic queues on the current uni for the given service
415 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "tp-id": sq.tpID,
420 "device-id": f.deviceHandler.device.Id})
421 // The upstream scheduler is already created. We only need to create the queues
422 // If there are multiple upstream flows on a given uni, then it is possible that
423 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
424 // TODO: Find better mechanism to not duplicate request.
425 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
426 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
427 log.Fields{"intf-id": sq.intfID,
428 "direction": sq.direction,
429 "device-id": f.deviceHandler.device.Id}, err)
430 }
431 } else {
432 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
433 log.Fields{"intf-id": sq.intfID,
434 "onu-id": sq.onuID,
435 "uni-id": sq.uniID,
436 "tp-id": sq.tpID,
437 "device-id": f.deviceHandler.device.Id})
438 }
439 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000441
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530443 log.Fields{
444 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530445 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447
Girish Gowdraa482f272021-03-24 23:04:19 -0700448 found := false
449 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000450 if sq.flowMetadata != nil {
451 for _, meter := range sq.flowMetadata.Meters {
452 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700453 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700454 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700456 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530457 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 break
460 }
461 }
462 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000463 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530466 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 "reason": "Could-not-get-meterbands-from-flowMetadata",
468 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530469 "meter-id": sq.meterID,
470 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Gamze Abaka01174422021-03-10 06:55:27 +0000472
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700473 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530474 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
475 log.Fields{"intf-id": sq.intfID,
476 "direction": sq.direction,
477 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
479
salmansiddiqui7ac62132019-08-22 03:58:50 +0000480 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 * store the meter id on the KV store, for further reference.
482 */
yasin saplibddc2d72022-02-08 13:10:17 +0000483 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530484 return olterrors.NewErrAdapter("failed-updating-meter-id",
485 log.Fields{"onu-id": sq.onuID,
486 "meter-id": sq.meterID,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530490 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700491 "meter-info": meterInfo,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 return nil
494}
495
Girish Gowdraf3728b12022-02-02 21:46:51 -0800496func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
497 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
498 if err != nil {
499 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
503 }
504 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
505 log.Fields{"direction": sq.direction,
506 "traffic-queues": trafficQueues,
507 "device-id": f.deviceHandler.device.Id})
508 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
509 UniId: sq.uniID, PortNo: sq.uniPort,
510 TrafficQueues: trafficQueues,
511 TechProfileId: TrafficSched[0].TechProfileId}
512 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
513 if len(queues.TrafficQueues) > 1 {
514 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
515 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
516 }
517 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
518 }
519 return err
520}
521
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700522func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700523 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000524
525 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530526 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
527 log.Fields{"intf-id": sq.intfID,
528 "direction": sq.direction,
529 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000530 }
531
Gamze Abakacb0e6772021-06-10 08:32:12 +0000532 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
533 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
534 log.Fields{
535 "direction": sq.direction,
536 "TrafficScheds": TrafficSched,
537 "device-id": f.deviceHandler.device.Id,
538 "intfID": sq.intfID,
539 "onuID": sq.onuID,
540 "uniID": sq.uniID})
541 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
542 IntfId: sq.intfID, OnuId: sq.onuID,
543 UniId: sq.uniID, PortNo: sq.uniPort,
544 TrafficScheds: TrafficSched}); err != nil {
545 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
546 }
547 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
548 "direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551 }
552
553 // On receiving the CreateTrafficQueues request, the driver should create corresponding
554 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530556 log.Fields{"direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000559 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
560 UniId: sq.uniID, PortNo: sq.uniPort,
561 TrafficQueues: trafficQueues,
562 TechProfileId: TrafficSched[0].TechProfileId}
563 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
564 if len(queues.TrafficQueues) > 1 {
565 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
566 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
567 }
568 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530569 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000571 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530572 "direction": sq.direction,
573 "traffic-queues": trafficQueues,
574 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700577 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000578 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700579 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
581 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 gemPortID: multicastQueuePerPonPort.GemportId,
586 servicePriority: multicastQueuePerPonPort.Priority,
587 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700588 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 //also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000590 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700591 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400592 return err
593 }
Shrey Baid26912972020-04-16 21:02:31 +0530594
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 }
597 }
598 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599 return nil
600}
601
Girish Gowdraf3728b12022-02-02 21:46:51 -0800602// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
603func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
604 var err error
605 logger.Infow(ctx, "removing-queue-in-olt",
606 log.Fields{
607 "direction": sq.direction,
608 "intf-id": sq.intfID,
609 "onu-id": sq.onuID,
610 "uni-id": sq.uniID,
611 "uni-port": sq.uniPort,
612 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613
Girish Gowdraf3728b12022-02-02 21:46:51 -0800614 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
615 if err != nil {
616 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
617 log.Fields{
618 "intf-id": sq.intfID,
619 "direction": sq.direction,
620 "device-id": f.deviceHandler.device.Id}, err)
621 }
622
623 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
624 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
625 UniId: sq.uniID, PortNo: sq.uniPort,
626 TrafficQueues: TrafficQueues,
627 TechProfileId: sq.tpID}); err != nil {
628 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
629 log.Fields{
630 "intf-id": sq.intfID,
631 "traffic-queues": TrafficQueues,
632 "device-id": f.deviceHandler.device.Id}, err)
633 }
634 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
635
636 return err
637}
638
639// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
640func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 var Direction string
642 var SchedCfg *tp_pb.SchedulerConfig
643 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800644 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530645 log.Fields{
646 "direction": sq.direction,
647 "intf-id": sq.intfID,
648 "onu-id": sq.onuID,
649 "uni-id": sq.uniID,
650 "uni-port": sq.uniPort,
651 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000652 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700653 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000655 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700656 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400657 Direction = "downstream"
658 }
659
Girish Gowdraa482f272021-03-24 23:04:19 -0700660 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700662 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664
Girish Gowdraf3728b12022-02-02 21:46:51 -0800665 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
666 IntfId: sq.intfID, OnuId: sq.onuID,
667 UniId: sq.uniID, PortNo: sq.uniPort,
668 TrafficScheds: TrafficSched}); err != nil {
669 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530670 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800671 "intf-id": sq.intfID,
672 "traffic-schedulers": TrafficSched,
673 "onu-id": sq.onuID,
674 "uni-id": sq.uniID,
675 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000676 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
679 log.Fields{"device-id": f.deviceHandler.device.Id,
680 "intf-id": sq.intfID,
681 "onu-id": sq.onuID,
682 "uni-id": sq.uniID,
683 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684
Girish Gowdraf3728b12022-02-02 21:46:51 -0800685 if sq.direction == tp_pb.Direction_UPSTREAM {
686 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
687 // Delete the TCONT on the ONU.
688 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000689 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800690 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
691 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000692 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800693 "intf": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "device-id": f.deviceHandler.device.Id,
697 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000698 }
699 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000700
701 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 * delete the meter id on the KV store.
703 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800704 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 return err
706}
707
Girish Gowdra197acc12021-08-16 10:59:45 -0700708// We are trying to force remove the schedulers and queues here if one exists for the given key.
709// We ignore any errors encountered in the process. The errors most likely are encountered when
710// the schedulers and queues are already cleared for the given key.
711func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
712
713 var schedCfg *tp_pb.SchedulerConfig
714 var err error
715 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
716 log.Fields{
717 "direction": sq.direction,
718 "intf-id": sq.intfID,
719 "onu-id": sq.onuID,
720 "uni-id": sq.uniID,
721 "uni-port": sq.uniPort,
722 "tp-id": sq.tpID,
723 "device-id": f.deviceHandler.device.Id})
724 if sq.direction == tp_pb.Direction_UPSTREAM {
725 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
726 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
727 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
728 }
729
730 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
731 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
732 TrafficSched[0].TechProfileId = sq.tpID
733
734 // Remove traffic queues. Ignore any errors, just log them.
735 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
736 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
737 "direction": sq.direction,
738 "intf-id": sq.intfID,
739 "onu-id": sq.onuID,
740 "uni-id": sq.uniID,
741 "uni-port": sq.uniPort,
742 "tp-id": sq.tpID,
743 "device-id": f.deviceHandler.device.Id,
744 "err": err})
745 } else {
746 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
747 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
748 UniId: sq.uniID, PortNo: sq.uniPort,
749 TrafficQueues: TrafficQueues,
750 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
751 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
752 "direction": sq.direction,
753 "intf-id": sq.intfID,
754 "onu-id": sq.onuID,
755 "uni-id": sq.uniID,
756 "uni-port": sq.uniPort,
757 "tp-id": sq.tpID,
758 "device-id": f.deviceHandler.device.Id,
759 "err": err})
760
761 } else {
762 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
763 "direction": sq.direction,
764 "intf-id": sq.intfID,
765 "onu-id": sq.onuID,
766 "uni-id": sq.uniID,
767 "uni-port": sq.uniPort,
768 "tp-id": sq.tpID})
769 }
770 }
771
772 // Remove traffic schedulers. Ignore any errors, just log them.
773 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
774 IntfId: sq.intfID, OnuId: sq.onuID,
775 UniId: sq.uniID, PortNo: sq.uniPort,
776 TrafficScheds: TrafficSched}); err != nil {
777 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
778 "direction": sq.direction,
779 "intf-id": sq.intfID,
780 "onu-id": sq.onuID,
781 "uni-id": sq.uniID,
782 "uni-port": sq.uniPort,
783 "tp-id": sq.tpID,
784 "device-id": f.deviceHandler.device.Id,
785 "err": err})
786 } else {
787 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
788 "direction": sq.direction,
789 "intf-id": sq.intfID,
790 "onu-id": sq.onuID,
791 "uni-id": sq.uniID,
792 "uni-port": sq.uniPort,
793 "tp-id": sq.tpID})
794 }
795}
796
Gamze Abakafee36392019-10-03 11:17:24 +0000797// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400798func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000799 var allocIDs []uint32
800 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530802 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000803 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000804 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
805 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
806 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530807
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530809 "intf-id": intfID,
810 "onu-id": onuID,
811 "uni-id": uniID,
812 "device-id": f.deviceHandler.device.Id,
813 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530814
Manikkaraj kb1d51442019-07-23 10:41:02 -0400815 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700816 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000817 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530819 log.Fields{
820 "path": tpPath,
821 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700822 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000823 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530824 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530826 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700827 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530828 "tp-id": TpID,
829 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000830 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
yasin saplibddc2d72022-02-08 13:10:17 +0000832 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700833 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400834 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530837 log.Fields{
838 "uni": uni,
839 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530840 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530841 }
Gamze Abakafee36392019-10-03 11:17:24 +0000842
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700844 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700845 if UsMeterID != 0 {
846 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
847 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
848 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700851 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700852 "onu-id": onuID,
853 "uni-id": uniID,
854 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 "meter-id": UsMeterID,
856 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000857 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700858 return 0, nil, nil
859 }
860 }
861 if DsMeterID != 0 {
862 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
863 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
864 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700868 "onu-id": onuID,
869 "uni-id": uniID,
870 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 "meter-id": DsMeterID,
872 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000873 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 return 0, nil, nil
875 }
876 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700879 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700881 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000882
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700883 if tpInstanceExists {
884 return allocID, gemPortIDs, techProfileInstance
885 }
886
887 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700888 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000890 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700892 "intf-id": intfID,
893 "onu-id": onuID,
894 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 "alloc-ids": allocIDs,
896 "gemports": allgemPortIDs,
897 "device-id": f.deviceHandler.device.Id})
898 // Send Tconts and GEM ports to KV store
899 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530900 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400901 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 // CreateSchedulerQueues for EPON needs to be implemented here
903 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700906 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700908 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909
910 if tpInstanceExists {
911 return allocID, gemPortIDs, techProfileInstance
912 }
913
914 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700915 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 log.Fields{
919 "alloc-ids": allocIDs,
920 "gemports": allgemPortIDs,
921 "device-id": f.deviceHandler.device.Id})
922 // Send Tconts and GEM ports to KV store
923 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
924 return allocID, gemPortIDs, techProfileInstance
925 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700927 log.Fields{
928 "tpInst": tpInst})
929 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530930 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530931}
932
npujarec5762e2020-01-01 14:08:48 +0530933func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530934
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530936 log.Fields{
937 "intf-id": intfID,
938 "onu-id": onuID,
939 "uni-id": uniID,
940 "alloc-id": allocID,
941 "gemport-ids": gemPortIDs,
942 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530943 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000944 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000945 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "allocID": allocID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530946 }
yasin saplibddc2d72022-02-08 13:10:17 +0000947 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000948 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530949 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950
Neha Sharma96b7bf22020-06-15 10:37:32 +0000951 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400952 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000953 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000954 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
955 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400956 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530957}
958
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700959func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000961 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700962 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
963 var err error
964 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
965 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
966 if err != nil || f.techprofile == nil {
967 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
968 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
969 }
970 logger.Debugw(ctx, "init-tech-profile-done",
971 log.Fields{
972 "intf-id": intfID,
973 "device-id": f.deviceHandler.device.Id})
974 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700975 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 }
977 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700978 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
979 return fmt.Errorf("pon-port-idx-not-found-in-the-device-info-pon-port-range-%v", f.ponPortIdx)
manikkaraj kbf256be2019-03-25 00:13:48 +0530980}
981
Gamze Abaka7650be62021-02-26 10:50:36 +0000982func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800983 flowContext.classifier[PacketTagType] = SingleTag
984 // extract the cvid/inner-vid from the write metadata
985 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
986 if writeMetadata != 0 {
987 // Writemetadata field is 8 bytes
988 // cvid is on the outer most two bytes of the write metadata
989 cvid := (writeMetadata & 0xffff000000000000) >> 48
990 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
991 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
992 flowContext.classifier[PacketTagType] = DoubleTag
993 }
994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530996 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 "uplinkClassifier": flowContext.classifier,
998 "uplinkAction": flowContext.action})
999 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301000}
1001
Gamze Abaka7650be62021-02-26 10:50:36 +00001002func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1003 downlinkClassifier := flowContext.classifier
1004 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001005 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1006 downlinkClassifier[PacketTagType] = SingleTag
1007 // extract the cvid/inner-vid from the write metadata
1008 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1009 if writeMetadata != 0 {
1010 // Writemetadata field is 8 bytes
1011 // cvid is on the outer most two bytes of the write metadata
1012 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1013 downlinkClassifier[PacketTagType] = DoubleTag
1014 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301015 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301017 log.Fields{
1018 "downlinkClassifier": downlinkClassifier,
1019 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001020 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1021 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1022 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001023 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001024 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001025 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301026 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001027 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301028 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001029 "onu-id": flowContext.onuID,
1030 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001032 }
1033 }
1034 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301035 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001036
Girish Gowdraffa52e52022-02-16 15:48:10 -08001037 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1038 // The matched vlan is the one that is getting popped.
1039 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1040 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1041 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1042 if ok {
1043 downlinkAction[VlanVid] = dlClVid & 0xfff
1044 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301045 }
1046
Gamze Abaka7650be62021-02-26 10:50:36 +00001047 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301048}
1049
Gamze Abaka7650be62021-02-26 10:50:36 +00001050func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001051
Gamze Abaka7650be62021-02-26 10:50:36 +00001052 intfID := flowContext.intfID
1053 onuID := flowContext.onuID
1054 uniID := flowContext.uniID
1055 classifier := flowContext.classifier
1056 action := flowContext.action
1057 allocID := flowContext.allocID
1058 gemPortID := flowContext.gemPortID
1059 tpID := flowContext.tpID
1060 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001061 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301062 log.Fields{
1063 "intf-id": intfID,
1064 "onu-id": onuID,
1065 "uni-id": uniID,
1066 "device-id": f.deviceHandler.device.Id,
1067 "classifier": classifier,
1068 "action": action,
1069 "direction": direction,
1070 "alloc-id": allocID,
1071 "gemport-id": gemPortID,
1072 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001073
yasin saplibddc2d72022-02-08 13:10:17 +00001074 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001075 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "device-id": f.deviceHandler.device.Id,
1079 "intf-id": intfID,
1080 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 return nil
yasin saplid0566272021-12-21 09:10:30 +00001082 } else if err != nil {
1083 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1084 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1085 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301086 }
yasin saplid0566272021-12-21 09:10:30 +00001087
David K. Bainbridge794735f2020-02-11 21:01:37 -08001088 classifierProto, err := makeOpenOltClassifierField(classifier)
1089 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301090 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301091 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "classifier": *classifierProto,
1095 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001096 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301098 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301099 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001100 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301101 log.Fields{
1102 "action": *actionProto,
1103 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301105 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 log.Fields{
1108 "classifier": classifier,
1109 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301110 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301112 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001113
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001115 OnuId: int32(onuID),
1116 UniId: int32(uniID),
1117 FlowId: logicalFlow.Id,
1118 FlowType: direction,
1119 AllocId: int32(allocID),
1120 NetworkIntfId: int32(networkIntfID),
1121 GemportId: int32(gemPortID),
1122 Classifier: classifierProto,
1123 Action: actionProto,
1124 Priority: int32(logicalFlow.Priority),
1125 Cookie: logicalFlow.Cookie,
1126 PortNo: flowContext.portNo,
1127 TechProfileId: tpID,
1128 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1129 PbitToGemport: flowContext.pbitToGem,
1130 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001131 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001133 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301134 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001135 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301136 log.Fields{"direction": direction,
1137 "device-id": f.deviceHandler.device.Id,
1138 "flow": flow,
1139 "intf-id": intfID,
1140 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001141
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301143}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001144
Gamze Abaka7650be62021-02-26 10:50:36 +00001145func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1146
1147 intfID := flowContext.intfID
1148 onuID := flowContext.onuID
1149 uniID := flowContext.uniID
1150 logicalFlow := flowContext.logicalFlow
1151 classifier := flowContext.classifier
1152 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301155 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301158 "action": action,
1159 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301161 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162
1163 // Clear the action map
1164 for k := range action {
1165 delete(action, k)
1166 }
1167
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 action[TrapToHost] = true
1169 classifier[UDPSrc] = uint32(68)
1170 classifier[UDPDst] = uint32(67)
1171 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301172
yasin saplibddc2d72022-02-08 13:10:17 +00001173 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001174 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001175 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301176 log.Fields{
1177 "device-id": f.deviceHandler.device.Id,
1178 "intf-id": intfID,
1179 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 return nil
yasin saplid0566272021-12-21 09:10:30 +00001181 } else if err != nil {
1182 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1183 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1184 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301185 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301188 log.Fields{
1189 "ul_classifier": classifier,
1190 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001191 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301192 "intf-id": intfID,
1193 "onu-id": onuID,
1194 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301195
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 classifierProto, err := makeOpenOltClassifierField(classifier)
1197 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301198 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001201 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301203 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301204 }
1205
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001207 OnuId: int32(onuID),
1208 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001210 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001211 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001213 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301214 Classifier: classifierProto,
1215 Action: actionProto,
1216 Priority: int32(logicalFlow.Priority),
1217 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001218 PortNo: flowContext.portNo,
1219 TechProfileId: flowContext.tpID,
1220 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1221 PbitToGemport: flowContext.pbitToGem,
1222 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001223 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001225 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301228 log.Fields{
1229 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001230 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301231 "intf-id": intfID,
1232 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301233
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301235}
1236
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001238func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1239 delete(flowContext.classifier, VlanVid)
1240 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241}
1242
1243//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001244func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1245
1246 intfID := flowContext.intfID
1247 onuID := flowContext.onuID
1248 uniID := flowContext.uniID
1249 logicalFlow := flowContext.logicalFlow
1250 classifier := flowContext.classifier
1251 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001252
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301255 return olterrors.NewErrNotFound("nni-interface-id",
1256 log.Fields{
1257 "classifier": classifier,
1258 "action": action,
1259 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 }
1262
1263 // Clear the action map
1264 for k := range action {
1265 delete(action, k)
1266 }
1267
1268 action[TrapToHost] = true
1269 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270
yasin saplibddc2d72022-02-08 13:10:17 +00001271 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001272 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 return nil
yasin saplid0566272021-12-21 09:10:30 +00001275 } else if err != nil {
1276 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1277 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1278 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279 }
1280
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301282 log.Fields{
1283 "ul_classifier": classifier,
1284 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001285 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301286 "device-id": f.deviceHandler.device.Id,
1287 "intf-id": intfID,
1288 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001289
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 classifierProto, err := makeOpenOltClassifierField(classifier)
1291 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301292 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001294 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301295 log.Fields{
1296 "classifier": *classifierProto,
1297 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001298 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301300 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001301 }
1302
David K. Bainbridge794735f2020-02-11 21:01:37 -08001303 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304 OnuId: int32(onuID),
1305 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001306 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001307 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001308 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001310 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311 Classifier: classifierProto,
1312 Action: actionProto,
1313 Priority: int32(logicalFlow.Priority),
1314 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001315 PortNo: flowContext.portNo,
1316 TechProfileId: flowContext.tpID,
1317 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1318 PbitToGemport: flowContext.pbitToGem,
1319 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001320 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001321
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001323 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 -08001324 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001325
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001327}
1328
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001329// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001330func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1331 intfID := flowContext.intfID
1332 onuID := flowContext.onuID
1333 uniID := flowContext.uniID
1334 portNo := flowContext.portNo
1335 allocID := flowContext.allocID
1336 gemPortID := flowContext.gemPortID
1337 logicalFlow := flowContext.logicalFlow
1338 classifier := flowContext.classifier
1339 action := flowContext.action
1340
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001341 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301342 log.Fields{
1343 "intf-id": intfID,
1344 "onu-id": onuID,
1345 "port-no": portNo,
1346 "alloc-id": allocID,
1347 "gemport-id": gemPortID,
1348 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001349 "flow": logicalFlow,
1350 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301351
1352 uplinkClassifier := make(map[string]interface{})
1353 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301354
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001356 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357 uplinkClassifier[PacketTagType] = SingleTag
1358 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001359 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001362 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001363 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001367 "intf-id": intfID,
1368 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 return nil
yasin saplid0566272021-12-21 09:10:30 +00001370 } else if err != nil {
1371 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1372 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1373 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301374 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001375 //Add Uplink EthType Flow
1376 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301377 log.Fields{
1378 "ul_classifier": uplinkClassifier,
1379 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001380 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301381 "device-id": f.deviceHandler.device.Id,
1382 "intf-id": intfID,
1383 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301384
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1386 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301387 return olterrors.NewErrInvalidValue(log.Fields{
1388 "classifier": uplinkClassifier,
1389 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001391 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301392 log.Fields{
1393 "classifier": *classifierProto,
1394 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001395 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301397 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301398 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301400 log.Fields{
1401 "action": *actionProto,
1402 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301404 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301405 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001406 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301407 "action": action,
1408 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301410 }
1411
David K. Bainbridge794735f2020-02-11 21:01:37 -08001412 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 OnuId: int32(onuID),
1414 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001416 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001417 AllocId: int32(allocID),
1418 NetworkIntfId: int32(networkIntfID),
1419 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301420 Classifier: classifierProto,
1421 Action: actionProto,
1422 Priority: int32(logicalFlow.Priority),
1423 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001424 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001425 TechProfileId: flowContext.tpID,
1426 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1427 PbitToGemport: flowContext.pbitToGem,
1428 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001429 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001430 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001431 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001433 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301434 log.Fields{
1435 "device-id": f.deviceHandler.device.Id,
1436 "onu-id": onuID,
1437 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001438 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301439 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001440
David K. Bainbridge794735f2020-02-11 21:01:37 -08001441 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301442}
1443
David K. Bainbridge794735f2020-02-11 21:01:37 -08001444func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446
1447 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1448 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1449 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001450 if vlanID != ReservedVlan {
1451 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001452 classifier.OVid = vid
1453 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301454 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301455 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001456 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1457 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301458 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1459 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1460 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1461 // becomes the IVid.
1462 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1463 if vid != ReservedVlan {
1464 classifier.IVid = vid
1465 }
1466 } else {
1467 if vid != ReservedVlan {
1468 classifier.OVid = vid
1469 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001470 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301471 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301472 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001473 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301474 classifier.OPbits = vlanPcp
1475 } else {
1476 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001478 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1479 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1480 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1481 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001482 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001483 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001484 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1485 classifier.PktTagType = pktTagType
1486
1487 switch pktTagType {
1488 case SingleTag:
1489 case DoubleTag:
1490 case Untagged:
1491 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001492 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301493 }
1494 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001495 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301496}
1497
Gamze Abaka724d0852020-03-18 12:10:24 +00001498func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499 var actionCmd openoltpb2.ActionCmd
1500 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301501 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001503 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301504 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001505 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001506 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001507 action.Cmd.RemarkInnerPbits = true
1508 action.IPbits = actionInfo[VlanPcp].(uint32)
1509 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001510 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001511 action.Cmd.TranslateInnerTag = true
1512 action.IVid = actionInfo[VlanVid].(uint32)
1513 }
1514 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001516 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301518 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001519 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001520 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001521 action.OPbits = actionInfo[VlanPcp].(uint32)
1522 action.Cmd.RemarkOuterPbits = true
1523 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001524 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001525 action.IVid = classifierInfo[VlanVid].(uint32)
1526 action.Cmd.TranslateInnerTag = true
1527 }
1528 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529 } else if _, ok := actionInfo[TrapToHost]; ok {
1530 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001531 } else if _, ok := actionInfo[VlanVid]; ok {
1532 // Translate outer vid
1533 action.Cmd.TranslateOuterTag = true
1534 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301535 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301536 // When OLT is transparent to vlans no-action is valid.
1537 /*
1538 else {
1539 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1540 }
1541 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001542 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301543}
1544
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001545// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001546func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001547 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301548}
1549
Gamze Abakafee36392019-10-03 11:17:24 +00001550// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001551// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1552// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1553// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1554// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1555// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1556// because it was observed that if the ONU device was deleted too soon after the flows were
1557// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1558// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1559// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001560func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001561 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001562 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1563
Gamze Abakafee36392019-10-03 11:17:24 +00001564 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001565
1566 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001567 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001568 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001569 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001570 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1571 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1572 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1573 log.Fields{
1574 "tp-id": tpID,
1575 "path": tpPath})
1576 }
1577 switch tpInstance := tpInst.(type) {
1578 case *tp_pb.TechProfileInstance:
1579 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1580 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1581 }
1582 // Force cleanup scheduler/queues -- end
1583
1584 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301585 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001586 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301587 // return err
1588 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001589 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 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 +00001591 }
1592 return nil
1593}
1594
1595// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301596func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001597 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001598 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001599 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001600 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301601 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1602 log.Fields{
1603 "tp-id": tpID,
1604 "uni-port-name": uniPortName,
1605 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 }
1607 return nil
1608}
1609
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001611
1612 var intfID uint32
1613 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1614 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1615 */
1616 if deviceFlow.AccessIntfId != -1 {
1617 intfID = uint32(deviceFlow.AccessIntfId)
1618 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001619 // We need to log the valid interface ID.
1620 // 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 +00001621 intfID = uint32(deviceFlow.NetworkIntfId)
1622 }
1623
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301625 "flow": *deviceFlow,
1626 "device-id": f.deviceHandler.device.Id,
1627 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001628 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 st, _ := status.FromError(err)
1631 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001632 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001633 "err": err,
1634 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301635 "device-id": f.deviceHandler.device.Id,
1636 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001637 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301638 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001639
1640 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301642 log.Fields{"err": err,
1643 "device-flow": deviceFlow,
1644 "device-id": f.deviceHandler.device.Id,
1645 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001646 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "flow": *deviceFlow,
1651 "device-id": f.deviceHandler.device.Id,
1652 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001653
yasin saplid0566272021-12-21 09:10:30 +00001654 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1655 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1656 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001657 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001659}
1660
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1662 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "flow": *deviceFlow,
1665 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001666 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001667 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001668 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301670 log.Fields{
1671 "err": err,
1672 "deviceFlow": deviceFlow,
1673 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001674 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001676 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001677 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001678
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001681 "of-flow-id": ofFlowID,
1682 "flow": *deviceFlow,
1683 "device-id": f.deviceHandler.device.Id,
1684 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301686}
1687
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001689
1690 classifierInfo := make(map[string]interface{})
1691 actionInfo := make(map[string]interface{})
1692
1693 classifierInfo[EthType] = uint32(LldpEthType)
1694 classifierInfo[PacketTagType] = Untagged
1695 actionInfo[TrapToHost] = true
1696
1697 // LLDP flow is installed to trap LLDP packets on the NNI port.
1698 // We manage flow_id resource pool on per PON port basis.
1699 // Since this situation is tricky, as a hack, we pass the NNI port
1700 // index (network_intf_id) as PON port Index for the flow_id resource
1701 // pool. Also, there is no ONU Id available for trapping LLDP packets
1702 // on NNI port, use onu_id as -1 (invalid)
1703 // ****************** CAVEAT *******************
1704 // This logic works if the NNI Port Id falls within the same valid
1705 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1706 // we need to have a re-look at this.
1707 // *********************************************
1708
1709 var onuID = -1
1710 var uniID = -1
1711 var gemPortID = -1
1712
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001713 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001714 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301715 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 }
yasin saplibddc2d72022-02-08 13:10:17 +00001717 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001718 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 return nil
yasin saplid0566272021-12-21 09:10:30 +00001721 } else if err != nil {
1722 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1723 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1724 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001725 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001726
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1728 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301729 return olterrors.NewErrInvalidValue(
1730 log.Fields{
1731 "classifier": classifierInfo,
1732 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001734 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301735 log.Fields{
1736 "classifier": *classifierProto,
1737 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001738 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001739 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301740 return olterrors.NewErrInvalidValue(
1741 log.Fields{
1742 "action": actionInfo,
1743 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301746 log.Fields{
1747 "action": *actionProto,
1748 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001749
1750 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1751 OnuId: int32(onuID), // OnuId not required
1752 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001753 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001754 FlowType: Downstream,
1755 NetworkIntfId: int32(networkInterfaceID),
1756 GemportId: int32(gemPortID),
1757 Classifier: classifierProto,
1758 Action: actionProto,
1759 Priority: int32(flow.Priority),
1760 Cookie: flow.Cookie,
1761 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001763 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301764 log.Fields{
1765 "flow": downstreamflow,
1766 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001767 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001768 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301769 log.Fields{
1770 "device-id": f.deviceHandler.device.Id,
1771 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001772 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001773
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301775}
1776
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001777func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1778 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001779}
1780
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001783 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1784 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1785 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001786 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301787 log.Fields{
1788 "intf-id": intfID,
1789 "onu-id": onuID,
1790 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301793 return nil, olterrors.NewErrNotFound("onu-child-device",
1794 log.Fields{
1795 "onu-id": onuID,
1796 "intf-id": intfID,
1797 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
khenaidoo106c61a2021-08-11 18:05:46 -04001799 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 -07001800 //better to ad the device to cache here.
1801 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1802 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "intf-id": intfID,
1806 "onu-id": onuID,
1807 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001808 }
1809
1810 return onuDev.(*OnuDevice), nil
1811}
1812
1813//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1815 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301816 log.Fields{
1817 "pon-port": intfID,
1818 "onu-id": onuID,
1819 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001820 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001822 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301823 return nil, olterrors.NewErrNotFound("onu",
1824 log.Fields{
1825 "interface-id": parentPortNo,
1826 "onu-id": onuID,
1827 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001828 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301831 log.Fields{
1832 "device-id": f.deviceHandler.device.Id,
1833 "child_device_id": onuDevice.Id,
1834 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301835 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301836}
1837
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1839 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301840 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301842 log.Fields{
1843 "intf-id": intfID,
1844 "onu-id": onuID,
1845 "uni-id": uniID,
1846 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001847 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 }
1849
khenaidoodc2116e2021-10-19 17:33:19 -04001850 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001851 DeviceId: onuDev.deviceID,
1852 UniId: uniID,
1853 TpInstancePath: tpPath,
1854 GemPortId: gemPortID,
1855 }
1856 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1857
1858 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301859 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1860 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001861 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1862 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301863 "onu-id": onuDev.deviceID,
1864 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001865 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301866 }
khenaidoo106c61a2021-08-11 18:05:46 -04001867
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301869 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001870 "msg": delGemPortMsg,
1871 "from-adapter": f.deviceHandler.device.Type,
1872 "to-adapter": onuDev.deviceType,
1873 "device-id": f.deviceHandler.device.Id,
1874 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 return nil
1876}
1877
Neha Sharma96b7bf22020-06-15 10:37:32 +00001878func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1879 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301880 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001881 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301882 log.Fields{
1883 "intf-id": intfID,
1884 "onu-id": onuID,
1885 "uni-id": uniID,
1886 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001887 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 }
1889
khenaidoodc2116e2021-10-19 17:33:19 -04001890 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001891 DeviceId: onuDev.deviceID,
1892 UniId: uniID,
1893 TpInstancePath: tpPath,
1894 AllocId: allocID,
1895 }
1896
Neha Sharma96b7bf22020-06-15 10:37:32 +00001897 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301898 log.Fields{
1899 "msg": *delTcontMsg,
1900 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001901
1902 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301903 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1904 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001905 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1906 "to-adapter": onuDev.adapterEndpoint,
1907 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301908 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001909 "device-id": f.deviceHandler.device.Id}, err)
1910
Girish Gowdra6b130582019-11-20 16:45:20 +05301911 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301913 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001914 "msg": delTcontMsg,
1915 "device-id": f.deviceHandler.device.Id,
1916 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301917 return nil
1918}
1919
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301920//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001921// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001922func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001923 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001924
1925 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001926
Girish Gowdraa482f272021-03-24 23:04:19 -07001927 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001928 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001929 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1930 log.Fields{
1931 "tpPath": tpPath,
1932 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001933
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001934 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001935 if err != nil || techprofileInst == nil {
1936 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1937 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1938 if childDevice == nil {
1939 // happens when subscriber un-provision is immediately followed by child device delete
1940 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1941 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1942 return nil
1943 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001944 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1945 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001946 log.Fields{
1947 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001948 "path": tpPath}, err).Log()
1949 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001950 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001951
1952 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001954 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001955 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1956 gemPortID := gemPort.GemportId
yasin sapli9e4c5092022-02-01 13:52:33 +00001957 used := f.resourceMgr.IsGemPortUsedByAnotherFlow(gemPortID, flowID)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001958 if used {
yasin saplibddc2d72022-02-08 13:10:17 +00001959 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
yasin sapli9e4c5092022-02-01 13:52:33 +00001960 if err != nil {
1961 return err
1962 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001963 for i, flowIDinMap := range flowIDs {
1964 if flowIDinMap == flowID {
1965 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001966 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001967 return err
1968 }
1969 break
1970 }
1971 }
1972 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1973 log.Fields{
1974 "gemport-id": gemPortID,
1975 "usedByFlows": flowIDs,
1976 "currentFlow": flowID,
1977 "device-id": f.deviceHandler.device.Id})
1978 allGemPortsFree = false
1979 }
1980 }
1981 if !allGemPortsFree {
1982 return nil
1983 }
1984 }
1985
1986 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 -08001987
1988 // 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 +00001989 switch techprofileInst := techprofileInst.(type) {
1990 case *tp_pb.TechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00001991 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001992 logger.Warn(ctx, err)
1993 }
1994 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1995 logger.Warn(ctx, err)
1996 }
1997
1998 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1999 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00002000 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08002001
yasin saplibddc2d72022-02-08 13:10:17 +00002002 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002003 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2004 log.Fields{
2005 "err": err,
2006 "intf": intfID,
2007 "onu-id": onuID,
2008 "uni-id": uniID,
2009 "device-id": f.deviceHandler.device.Id,
2010 "gemport-id": gemPortID})
2011 }
2012
2013 }
2014 // Remove queues at OLT in upstream and downstream direction
2015 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2016 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2017 logger.Warn(ctx, err)
2018 }
2019 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2020 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2021 logger.Warn(ctx, err)
2022 }
2023 }
2024
2025 switch techprofileInst := techprofileInst.(type) {
2026 case *tp_pb.TechProfileInstance:
2027 // 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 +01002028 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2029 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2030 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002031 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002032 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002033 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002034 logger.Warn(ctx, err)
2035 }
2036 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002037 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002038 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002039 } else {
2040 // just remove meter reference for the upstream direction for the current pon/onu/uni
2041 // 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
2042 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2043 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002044 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002045 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2046 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002047 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002048 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002049
Girish Gowdraf3728b12022-02-02 21:46:51 -08002050 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2051 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002052 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002053 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2054 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002055 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002056 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002057 case *tp_pb.EponTechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00002058 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002059 logger.Warn(ctx, err)
2060 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002061 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002062 logger.Warn(ctx, err)
2063 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002064 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002065 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002066 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302067 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002068 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302069 "onu-id": onuID,
2070 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002071 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002072 "alloc-id": techprofileInst.AllocId,
2073 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002074 }
yasin saplibddc2d72022-02-08 13:10:17 +00002075 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 default:
2077 logger.Errorw(ctx, "error-unknown-tech",
2078 log.Fields{
2079 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002080 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002081
2082 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2083 switch techprofileInst := techprofileInst.(type) {
2084 case *tp_pb.TechProfileInstance:
2085 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2086 // Delete the gem port on the ONU.
2087 if sendDeleteGemRequest {
2088 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2089 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2090 log.Fields{
2091 "err": err,
2092 "intfID": intfID,
2093 "onu-id": onuID,
2094 "uni-id": uniID,
2095 "device-id": f.deviceHandler.device.Id,
2096 "gemport-id": gemPort.GemportId})
2097 }
yasin saplibddc2d72022-02-08 13:10:17 +00002098 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002099 }
2100 }
2101 }
2102
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302103 return nil
2104}
2105
David K. Bainbridge794735f2020-02-11 21:01:37 -08002106// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002107func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002108 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302109 log.Fields{
2110 "flowDirection": flowDirection,
2111 "flow": *flow,
2112 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002113
2114 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002115 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002116 }
2117
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302118 var ethType, ipProto, inPort uint32
2119 for _, field := range flows.GetOfbFields(flow) {
2120 if field.Type == flows.IP_PROTO {
2121 ipProto = field.GetIpProto()
2122 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2123 } else if field.Type == flows.ETH_TYPE {
2124 ethType = field.GetEthType()
2125 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2126 } else if field.Type == flows.IN_PORT {
2127 inPort = field.GetPort()
2128 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2129 }
2130 }
2131 portType := plt.IntfIDToPortTypeName(inPort)
2132 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2133 (portType == voltha.Port_ETHERNET_NNI) {
2134 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2135 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2136 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2137 // No more processing needed for trap from nni flows.
2138 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302139
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302140 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302141 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002142 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002143 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302144 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002145 onuID := int32(onu)
2146 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002147 tpID, err := getTpIDFromFlow(ctx, flow)
2148 if err != nil {
2149 return olterrors.NewErrNotFound("tp-id",
2150 log.Fields{
2151 "flow": flow,
2152 "intf-id": Intf,
2153 "onu-id": onuID,
2154 "uni-id": uniID,
2155 "device-id": f.deviceHandler.device.Id}, err)
2156 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302157
Neha Sharma96b7bf22020-06-15 10:37:32 +00002158 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302159 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002160 "flow-id": flow.Id,
2161 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302162 "onu-id": onuID,
2163 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302164
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002165 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2166 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002167 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2168 return err
2169 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002170
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002171 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002172 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2173 "flow-id": flow.Id,
2174 "device-id": f.deviceHandler.device.Id,
2175 "onu-id": onuID,
2176 "intf": Intf,
2177 "err": err,
2178 })
2179 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302180 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002181
Girish Gowdra82c80982021-03-26 16:22:02 -07002182 // 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 +00002183 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002184 return err
2185 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002186 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002187}
2188
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002189//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002190func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002191
Matteo Scandolof16389e2021-05-18 00:47:08 +00002192 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302193 var direction string
2194 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002195
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302196 for _, action := range flows.GetActions(flow) {
2197 if action.Type == flows.OUTPUT {
2198 if out := action.GetOutput(); out != nil {
2199 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002200 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302201 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002202 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002203 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002204 }
2205 }
2206 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002207
2208 if flows.HasGroup(flow) {
2209 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002210 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002211 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302212 direction = Upstream
2213 } else {
2214 direction = Downstream
2215 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302216
Girish Gowdracefae192020-03-19 18:14:10 -07002217 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002218 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002219
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002220 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002221}
2222
Esin Karamanae41e2b2019-12-17 18:13:13 +00002223//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2224func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002225 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002226 if ethType, ok := classifierInfo[EthType]; ok {
2227 if ethType.(uint32) == IPv4EthType {
2228 if ipProto, ok := classifierInfo[IPProto]; ok {
2229 if ipProto.(uint32) == IgmpProto {
2230 return true
2231 }
2232 }
2233 }
2234 }
2235 }
2236 return false
2237}
2238
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002239// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002240func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002241 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2242 // The device itself is going to be reset as part of deletion. So nothing to be done.
2243 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2244 return nil
2245 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002246 // Step1 : Fill flowControlBlock
2247 // Step2 : Push the flowControlBlock to ONU channel
2248 // Step3 : Wait on response channel for response
2249 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002250 startTime := time.Now()
2251 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002252 errChan := make(chan error)
2253 flowCb := flowControlBlock{
2254 ctx: ctx,
2255 addFlow: addFlow,
2256 flow: flow,
2257 flowMetadata: flowMetadata,
2258 errChan: &errChan,
2259 }
2260 inPort, outPort := getPorts(flow)
2261 var onuID uint32
2262 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002263 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002264 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002265 if f.flowHandlerRoutineActive[onuID] {
2266 // inPort or outPort is InvalidPort for trap-from-nni flows.
2267 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2268 // Send the flowCb on the ONU flow channel
2269 f.incomingFlows[onuID] <- flowCb
2270 // Wait on the channel for flow handlers return value
2271 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002272 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002273 return err
2274 }
2275 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2276 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002277}
2278
2279// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2280// 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 -07002281func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002282 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002283 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002284 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002285 // block on the channel to receive an incoming flow
2286 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002287 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002288 if flowCb.addFlow {
2289 logger.Info(flowCb.ctx, "adding-flow-start")
2290 startTime := time.Now()
2291 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2292 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2293 // Pass the return value over the return channel
2294 *flowCb.errChan <- err
2295 } else {
2296 logger.Info(flowCb.ctx, "removing-flow-start")
2297 startTime := time.Now()
2298 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2299 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2300 // Pass the return value over the return channel
2301 *flowCb.errChan <- err
2302 }
2303 case <-stopHandler:
2304 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2305 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002306 }
2307 }
2308}
2309
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002310// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002311func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002312 for i, v := range f.stopFlowHandlerRoutine {
2313 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002314 select {
2315 case v <- true:
2316 case <-time.After(time.Second * 5):
2317 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2318 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002319 }
2320 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002321 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002322 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2323}
2324
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002325// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302326// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002327func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002328 classifierInfo := make(map[string]interface{})
2329 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002330 var UsMeterID uint32
2331 var DsMeterID uint32
2332
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302334 log.Fields{
2335 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002336 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002337 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002338
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002340 if err != nil {
2341 // Error logging is already done in the called function
2342 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002343 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302344 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002345
Esin Karamanccb714b2019-11-29 15:02:06 +00002346 if flows.HasGroup(flow) {
2347 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002348 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002349 }
2350
manikkaraj k17652a72019-05-06 09:06:36 -04002351 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002353 if err != nil {
2354 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002355 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002356 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002357
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302359 log.Fields{
2360 "classifierinfo_inport": classifierInfo[InPort],
2361 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002362 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002363
Humera Kouser94d7a842019-08-25 19:04:32 -04002364 if ethType, ok := classifierInfo[EthType]; ok {
2365 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002366 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002367 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002368 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002369 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002370 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002371 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2372 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2373 }
2374 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002375 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002376 if ipProto, ok := classifierInfo[IPProto]; ok {
2377 if ipProto.(uint32) == IPProtoDhcp {
2378 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302379 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002381 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002382 }
2383 }
2384 }
2385 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002386 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002387 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002388 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002389 }
A R Karthick1f85b802019-10-11 05:06:05 +00002390
yasin saplibddc2d72022-02-08 13:10:17 +00002391 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002392
Girish Gowdra6071f382021-12-14 12:52:04 +05302393 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002394 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302395 return olterrors.NewErrNotFound("tpid-for-flow",
2396 log.Fields{
2397 "flow": flow,
2398 "intf-id": IntfID,
2399 "onu-id": onuID,
2400 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002401 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302403 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302404 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302405 "intf-id": intfID,
2406 "onu-id": onuID,
2407 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002408 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002409 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002410 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302411 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2412 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2413 return err
2414 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002415 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002416 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302418 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2419 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2420 return err
2421 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002422 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302423 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002424}
Girish Gowdra3d633032019-12-10 16:37:05 +05302425
Esin Karamanccb714b2019-11-29 15:02:06 +00002426// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002427func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302428 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002429 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302430 "classifier-info": classifierInfo,
2431 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002432
Esin Karaman65409d82020-03-18 10:58:18 +00002433 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002434 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002435 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002436 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002437
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002438 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002439
David K. Bainbridge794735f2020-02-11 21:01:37 -08002440 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002441
yasin saplibddc2d72022-02-08 13:10:17 +00002442 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002443 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002444 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002445 return nil
yasin saplid0566272021-12-21 09:10:30 +00002446 } else if err != nil {
2447 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2448 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2449 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002450 }
yasin saplid0566272021-12-21 09:10:30 +00002451
David K. Bainbridge794735f2020-02-11 21:01:37 -08002452 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2453 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002454 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002455 }
2456 groupID := actionInfo[GroupID].(uint32)
2457 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002458 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002459 FlowType: Multicast,
2460 NetworkIntfId: int32(networkInterfaceID),
2461 GroupId: groupID,
2462 Classifier: classifierProto,
2463 Priority: int32(flow.Priority),
2464 Cookie: flow.Cookie}
2465
Kent Hagermane6ff1012020-07-14 15:07:53 -04002466 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002467 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002468 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002469 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002470 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002471 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002472 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002473 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002474 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002475 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002476 //cached group can be removed now
2477 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002478 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002479 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002480 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002481
David K. Bainbridge794735f2020-02-11 21:01:37 -08002482 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002483}
2484
Esin Karaman65409d82020-03-18 10:58:18 +00002485//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2486func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2487 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002488 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002489 if err != nil {
2490 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2491 }
2492 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002493 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002494
2495 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2496 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002497}
2498
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002499//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002500func (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 -07002501
Neha Sharma96b7bf22020-06-15 10:37:32 +00002502 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302503 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302505 log.Fields{
2506 "intf-id": intfID,
2507 "onu-id": onuID,
2508 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002509 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302510 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002511 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002512
yasin saplibddc2d72022-02-08 13:10:17 +00002513 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002514 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002515 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002516 UniId: uniID,
2517 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002518 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002519 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002520 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002521
2522 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2523 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302524 return olterrors.NewErrCommunication("send-techprofile-download-request",
2525 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002526 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302527 "to-adapter": onuDev.deviceType,
2528 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002529 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002530 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002531 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302532 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302533}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002534
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002535//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302536func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002537 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538
2539 if packetIn.IntfType == "pon" {
2540 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002541 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002542 onuID, uniID := packetIn.OnuId, packetIn.UniId
2543 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 +00002544
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 if packetIn.PortNo != 0 {
2546 logicalPortNum = packetIn.PortNo
2547 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002548 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549 }
2550 // 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 +00002551 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002553 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002554 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002555
2556 if logger.V(log.DebugLevel) {
2557 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2558 log.Fields{
2559 "logical-port-num": logicalPortNum,
2560 "intf-type": packetIn.IntfType,
2561 "packet": hex.EncodeToString(packetIn.Pkt),
2562 })
2563 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002564 return logicalPortNum, nil
2565}
2566
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002567//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002568func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002569 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002570
2571 ctag, priority, err := getCTagFromPacket(ctx, packet)
2572 if err != nil {
2573 return 0, err
2574 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302575
Esin Karaman7fb80c22020-07-16 14:23:33 +00002576 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002577 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002578 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002579 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002580 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302581 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002582 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302583 log.Fields{
2584 "pktinkey": pktInkey,
2585 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002586
2587 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302589 //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 +00002590 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302591 if err == nil {
2592 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002593 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302594 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002595 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002596 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302597 log.Fields{
2598 "pktinkey": pktInkey,
2599 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600 return gemPortID, nil
2601 }
2602 }
Shrey Baid26912972020-04-16 21:02:31 +05302603 return uint32(0), olterrors.NewErrNotFound("gem-port",
2604 log.Fields{
2605 "pktinkey": pktInkey,
2606 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002607
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002608}
2609
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002610func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2611 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002612 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002613 classifier[PacketTagType] = DoubleTag
2614 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 /* We manage flowId resource pool on per PON port basis.
2616 Since this situation is tricky, as a hack, we pass the NNI port
2617 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002618 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 on NNI port, use onu_id as -1 (invalid)
2620 ****************** CAVEAT *******************
2621 This logic works if the NNI Port Id falls within the same valid
2622 range of PON Port Ids. If this doesn't work for some OLT Vendor
2623 we need to have a re-look at this.
2624 *********************************************
2625 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002626 onuID := -1
2627 uniID := -1
2628 gemPortID := -1
2629 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002630 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302631 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302632 return olterrors.NewErrNotFound("nni-intreface-id",
2633 log.Fields{
2634 "classifier": classifier,
2635 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002636 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 }
2638
yasin saplibddc2d72022-02-08 13:10:17 +00002639 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002640 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002641 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002642 return nil
yasin saplid0566272021-12-21 09:10:30 +00002643 } else if err != nil {
2644 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2645 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2646 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002648
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002649 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2650 log.Fields{
2651 "classifier": classifier,
2652 "action": action,
2653 "flowId": logicalFlow.Id,
2654 "intf-id": networkInterfaceID})
2655
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 classifierProto, err := makeOpenOltClassifierField(classifier)
2657 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002658 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002659 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002660 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002661 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002663 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002666 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2667 OnuId: int32(onuID), // OnuId not required
2668 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002669 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002670 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002671 AllocId: int32(allocID), // AllocId not used
2672 NetworkIntfId: int32(networkInterfaceID),
2673 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002674 Classifier: classifierProto,
2675 Action: actionProto,
2676 Priority: int32(logicalFlow.Priority),
2677 Cookie: logicalFlow.Cookie,
2678 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002680 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002681 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002682 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002683 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002685
Esin Karamanae41e2b2019-12-17 18:13:13 +00002686//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2687func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2688 var packetType string
2689 ovid, ivid := false, false
2690 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2691 vid := vlanID & VlanvIDMask
2692 if vid != ReservedVlan {
2693 ovid = true
2694 }
2695 }
2696 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2697 vid := uint32(metadata)
2698 if vid != ReservedVlan {
2699 ivid = true
2700 }
2701 }
2702 if ovid && ivid {
2703 packetType = DoubleTag
2704 } else if !ovid && !ivid {
2705 packetType = Untagged
2706 } else {
2707 packetType = SingleTag
2708 }
2709 return packetType
2710}
2711
2712//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002713func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002714 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002715 action := make(map[string]interface{})
2716 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2717 action[TrapToHost] = true
2718 /* We manage flowId resource pool on per PON port basis.
2719 Since this situation is tricky, as a hack, we pass the NNI port
2720 index (network_intf_id) as PON port Index for the flowId resource
2721 pool. Also, there is no ONU Id available for trapping packets
2722 on NNI port, use onu_id as -1 (invalid)
2723 ****************** CAVEAT *******************
2724 This logic works if the NNI Port Id falls within the same valid
2725 range of PON Port Ids. If this doesn't work for some OLT Vendor
2726 we need to have a re-look at this.
2727 *********************************************
2728 */
2729 onuID := -1
2730 uniID := -1
2731 gemPortID := -1
2732 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002733 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002734 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302735 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002736 "classifier": classifier,
2737 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002738 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002739 }
yasin saplibddc2d72022-02-08 13:10:17 +00002740 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002741 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002742 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002743 return nil
yasin saplid0566272021-12-21 09:10:30 +00002744 } else if err != nil {
2745 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2746 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2747 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002749
David K. Bainbridge794735f2020-02-11 21:01:37 -08002750 classifierProto, err := makeOpenOltClassifierField(classifier)
2751 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002752 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002754 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002755 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002756 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002757 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002758 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002759 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002760 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2761 OnuId: int32(onuID), // OnuId not required
2762 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002763 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002764 FlowType: Downstream,
2765 AllocId: int32(allocID), // AllocId not used
2766 NetworkIntfId: int32(networkInterfaceID),
2767 GemportId: int32(gemPortID), // GemportId not used
2768 Classifier: classifierProto,
2769 Action: actionProto,
2770 Priority: int32(logicalFlow.Priority),
2771 Cookie: logicalFlow.Cookie,
2772 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002773 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002774 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002775 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002776 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002777
David K. Bainbridge794735f2020-02-11 21:01:37 -08002778 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002779}
2780
salmansiddiqui7ac62132019-08-22 03:58:50 +00002781func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2782 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302783 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002784 }
2785 if Dir == tp_pb.Direction_UPSTREAM {
2786 return "upstream", nil
2787 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2788 return "downstream", nil
2789 }
2790 return "", nil
2791}
2792
Kent Hagermane6ff1012020-07-14 15:07:53 -04002793// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302794func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002795 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002796 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002797 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002798 intfID := args[IntfID]
2799 onuID := args[OnuID]
2800 uniID := args[UniID]
2801 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002802 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002803 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002804 gemToAes := make(map[uint32]bool)
2805
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002806 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002807 var direction = tp_pb.Direction_UPSTREAM
2808 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002809 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002810 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002811 attributes = TpInst.UpstreamGemPortAttributeList
2812 } else {
2813 attributes = TpInst.DownstreamGemPortAttributeList
2814 direction = tp_pb.Direction_DOWNSTREAM
2815 }
2816 default:
2817 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002818 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002819 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002820
2821 if len(gemPorts) == 1 {
2822 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002823 gemPortID = gemPorts[0]
2824 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002825 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2826 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002827 pBitMap := attributes[idx].PbitMap
2828 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2829 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2830 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002831 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002832 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2833 if pbitSet == pbit1 {
2834 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2835 pbitToGem[pcp] = gemID
2836 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002837 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002838 }
2839 }
2840 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002841 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2842 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2843 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002844 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002845 }
2846
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2848 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2849
salmansiddiqui7ac62132019-08-22 03:58:50 +00002850 if ipProto, ok := classifierInfo[IPProto]; ok {
2851 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002852 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002853 "tp-id": tpID,
2854 "alloc-id": allocID,
2855 "intf-id": intfID,
2856 "onu-id": onuID,
2857 "uni-id": uniID,
2858 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002859 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002860 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002861 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002862 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})
2863 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002864 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 }
2866
Girish Gowdra32625212020-04-29 11:26:35 -07002867 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002868 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302869 log.Fields{
2870 "intf-id": intfID,
2871 "onu-id": onuID,
2872 "uni-id": uniID,
2873 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002874 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002875 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002876 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})
2877 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002878 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002879 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002880 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002881 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002882 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002883 }
2884 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002885 if ethType.(uint32) == EapEthType {
2886 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002887 "intf-id": intfID,
2888 "onu-id": onuID,
2889 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002890 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002891 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 var vlanID uint32
2893 if val, ok := classifierInfo[VlanVid]; ok {
2894 vlanID = (val.(uint32)) & VlanvIDMask
2895 } else {
2896 vlanID = DefaultMgmtVlan
2897 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002898 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002899 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002900 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})
2901 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002902 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002903 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002904 } else if ethType.(uint32) == PPPoEDEthType {
2905 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2906 "tp-id": tpID,
2907 "alloc-id": allocID,
2908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID,
2911 })
2912 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002913 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002914 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002915 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})
2916 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002917 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002918 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002919 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002920 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002921 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002922 "intf-id": intfID,
2923 "onu-id": onuID,
2924 "uni-id": uniID,
2925 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002926 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002927 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002928 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002929 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})
2930 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002931 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002932 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002933 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002934 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002935 "intf-id": intfID,
2936 "onu-id": onuID,
2937 "uni-id": uniID,
2938 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002939 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002940 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002941 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002942 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})
2943 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002944 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 }
2946 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002947 return olterrors.NewErrInvalidValue(log.Fields{
2948 "intf-id": intfID,
2949 "onu-id": onuID,
2950 "uni-id": uniID,
2951 "classifier": classifierInfo,
2952 "action": actionInfo,
2953 "flow": flow},
2954 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002955 }
2956 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002957 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002958 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002959 logger.Warn(ctx, err)
2960 }
2961 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002962 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002963}
2964
Gamze Abakacb0e6772021-06-10 08:32:12 +00002965func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002966 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2967 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2968 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 +05302969 for i := 0; i < len(tpInstances); i++ {
2970 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002971 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002973 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002974 log.Fields{
2975 "device-id": f.deviceHandler.device.Id,
2976 "intfID": sq.intfID,
2977 "onuID": sq.onuID,
2978 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002979 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002980 })
2981 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302982 }
2983 }
2984 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002985 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002986}
2987
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002989 for _, field := range flows.GetOfbFields(flow) {
2990 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002993 } else if field.Type == flows.ETH_DST {
2994 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08002995 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
2996 } else if field.Type == flows.ETH_SRC {
2997 classifierInfo[EthSrc] = field.GetEthSrc()
2998 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002999 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003002 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003003 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003004 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003005 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303006 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3007 if field.GetVlanVid() != ReservedVlan {
3008 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3009 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3010 }
Scott Baker355d1742019-10-24 10:57:52 -07003011 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003014 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003017 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003026 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003027 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003029 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003033 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003034 return
3035 }
3036 }
3037}
3038
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003040 for _, action := range flows.GetActions(flow) {
3041 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003043 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003044 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003045 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003046 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 }
Scott Baker355d1742019-10-24 10:57:52 -07003048 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003049 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003051 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 if out := action.GetPush(); out != nil {
3053 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003054 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 } else {
3056 actionInfo[PushVlan] = true
3057 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003058 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303059 log.Fields{
3060 "push-tpid": actionInfo[TPID].(uint32),
3061 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003062 }
3063 }
Scott Baker355d1742019-10-24 10:57:52 -07003064 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003065 if out := action.GetSetField(); out != nil {
3066 if field := out.GetField(); field != nil {
3067 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003068 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3071 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003072 }
3073 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003074 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003076 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003077 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 }
3079 }
3080 return nil
3081}
3082
Neha Sharma96b7bf22020-06-15 10:37:32 +00003083func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003084 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003085 fieldtype := ofbField.GetType()
3086 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003087 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3088 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003090 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003092 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003093 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3094 pcp := ofbField.GetVlanPcp()
3095 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003096 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003097 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003099 }
3100 }
3101}
3102
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003104 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003106 } else {
3107 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003109 }
3110}
3111
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003113 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003116 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003117 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003118 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303120 log.Fields{
3121 "newinport": classifierInfo[InPort].(uint32),
3122 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303124 return olterrors.NewErrNotFound("child-in-port",
3125 log.Fields{
3126 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3127 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 }
3129 }
3130 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003133 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003134 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003135 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003136 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303137 log.Fields{
3138 "newoutport": actionInfo[Output].(uint32),
3139 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003140 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303141 return olterrors.NewErrNotFound("out-port",
3142 log.Fields{
3143 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3144 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003145 }
3146 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003147 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003148 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003150 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303151 log.Fields{
3152 "newinport": actionInfo[Output].(uint32),
3153 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303155 return olterrors.NewErrNotFound("nni-port",
3156 log.Fields{
3157 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3158 "in-port": classifierInfo[InPort].(uint32),
3159 "out-port": actionInfo[Output].(uint32),
3160 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003161 }
3162 }
3163 }
3164 return nil
3165}
Gamze Abakafee36392019-10-03 11:17:24 +00003166
Neha Sharma96b7bf22020-06-15 10:37:32 +00003167func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003168 /* Metadata 8 bytes:
3169 Most Significant 2 Bytes = Inner VLAN
3170 Next 2 Bytes = Tech Profile ID(TPID)
3171 Least Significant 4 Bytes = Port ID
3172 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3173 subscriber related flows.
3174 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003176 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003177 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003178 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003179 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003180 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003181}
3182
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003183func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003184 for _, sliceElement := range slice {
3185 if sliceElement == item {
3186 return slice
3187 }
3188 }
3189 return append(slice, item)
3190}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303191
3192// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303194
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003195 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303196 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003197 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003198 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003200 log.Fields{
3201 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003202 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003203 return uint32(0), err
3204 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303206 return intfID, nil
3207 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003208 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003209 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003211 log.Fields{
3212 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003213 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003214 return uint32(0), err
3215 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303217 return intfID, nil
3218 }
3219 return uint32(0), nil
3220}
3221
3222// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003223func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3224 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3225 if err != nil {
3226 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3227 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3228 return
3229 }
3230 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003231
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003232 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003233 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003234 f.packetInGemPortLock.RUnlock()
3235
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303236 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003237 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003238 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 +05303239 log.Fields{
3240 "pktinkey": pktInkey,
3241 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003242 return
3243 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303244 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003245 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003246 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003247 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003248
npujarec5762e2020-01-01 14:08:48 +05303249 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003250 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 +05303251 log.Fields{
3252 "pktinkey": pktInkey,
3253 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303254}
3255
Esin Karaman7fb80c22020-07-16 14:23:33 +00003256//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3257func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3258 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003259 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003260 return 0, 0, errors.New("invalid packet length")
3261 }
3262 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3263 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3264
3265 var index int8
3266 if outerEthType == 0x8100 {
3267 if innerEthType == 0x8100 {
3268 // q-in-q 802.1ad or 802.1q double tagged packet.
3269 // get the inner vlanId
3270 index = 18
3271 } else {
3272 index = 14
3273 }
3274 priority := (packet[index] >> 5) & 0x7
3275 //13 bits composes vlanId value
3276 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3277 return vlan, priority, nil
3278 }
3279 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3280 return 0, 0, nil
3281}
3282
Girish Gowdra9602eb42020-09-09 15:50:39 -07003283//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3284// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003285func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003286 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003287 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3288 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003289 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003290 "flow-id": flow.Id,
3291 "device-id": f.deviceHandler.device.Id})
3292 // Remove from device
3293 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3294 // DKB
3295 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3296 log.Fields{
3297 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003298 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003299 return err
3300 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003301
3302 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003303}
3304
khenaidoodc2116e2021-10-19 17:33:19 -04003305func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003306 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003307 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003308 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003309 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003310 }
3311
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003312 switch tpInst := tpInst.(type) {
3313 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003314 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003315 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003316 DeviceId: onuDeviceID,
3317 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003318 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003319 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003320 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003321 case *tp_pb.EponTechProfileInstance:
3322 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003323 DeviceId: onuDeviceID,
3324 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003325 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003326 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003327 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003328 default:
3329 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003330 }
khenaidoodc2116e2021-10-19 17:33:19 -04003331 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003332 DeviceId: onuDeviceID,
3333 UniId: uniID,
3334 TpInstancePath: tpPath,
3335 TechTpInstance: nil,
3336 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003337}
3338
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003339// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3340func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3341
3342 intfID := sq.intfID
3343 onuID := sq.onuID
3344 uniID := sq.uniID
3345 tpID := sq.tpID
3346
3347 var reverseDirection string
3348 if sq.direction == tp_pb.Direction_UPSTREAM {
3349 reverseDirection = "downstream"
3350 } else {
3351 reverseDirection = "upstream"
3352 }
3353
3354 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003355 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003356 return
3357 }
3358
3359 // revert-delete tech-profile instance and delete tech profile id for onu
3360 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})
3361 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3362 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003363 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003364
3365 // free gem/alloc
3366 switch techprofileInst := sq.tpInst.(type) {
3367 case *tp_pb.TechProfileInstance:
3368 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003369 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003370 }
yasin saplibddc2d72022-02-08 13:10:17 +00003371 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003372 }
3373}
3374
3375// revertSchduler is called when CreateQueues request fails
3376func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3377 // revert scheduler
3378 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})
3379 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3380 IntfId: sq.intfID, OnuId: sq.onuID,
3381 UniId: sq.uniID, PortNo: sq.uniPort,
3382 TrafficScheds: TrafficSched})
3383}
Girish Gowdra6071f382021-12-14 12:52:04 +05303384
3385// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3386func (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 +00003387 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303388 if err != nil {
3389 return olterrors.NewErrNotFound("meter",
3390 log.Fields{"intf-id": intfID,
3391 "onu-id": onuID,
3392 "uni-id": uniID,
3393 "device-id": f.deviceHandler.device.Id}, err)
3394 }
3395
3396 if meterInfo != nil {
3397 // If RefCnt become 0 clear the meter information from the DB.
3398 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003399 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303400 return err
3401 }
3402 } else if meterInfo.MeterID != meterID {
3403 logger.Errorw(ctx, "meter-mismatch-for-direction",
3404 log.Fields{"direction": direction,
3405 "kv-store-meter-id": meterInfo.MeterID,
3406 "meter-id-in-flow": meterID,
3407 "device-id": f.deviceHandler.device.Id})
3408 return olterrors.NewErrInvalidValue(log.Fields{
3409 "unsupported": "meter-id",
3410 "kv-store-meter-id": meterInfo.MeterID,
3411 "meter-id-in-flow": meterID,
3412 "device-id": f.deviceHandler.device.Id}, nil)
3413 }
3414 }
3415 return nil
3416}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003417
3418func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3419 /* After we successfully remove the scheduler configuration on the OLT device,
3420 * delete the meter id on the KV store.
3421 */
yasin saplibddc2d72022-02-08 13:10:17 +00003422 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003423 if err != nil {
3424 return olterrors.NewErrAdapter("unable-to-remove-meter",
3425 log.Fields{
3426 "onu": sq.onuID,
3427 "device-id": f.deviceHandler.device.Id,
3428 "intf-id": sq.intfID,
3429 "onu-id": sq.onuID,
3430 "uni-id": sq.uniID,
3431 "uni-port": sq.uniPort}, err)
3432 }
3433 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3434 log.Fields{
3435 "dir": direction,
3436 "device-id": f.deviceHandler.device.Id,
3437 "intf-id": sq.intfID,
3438 "onu-id": sq.onuID,
3439 "uni-id": sq.uniID,
3440 "uni-port": sq.uniPort})
3441 return err
3442}