blob: 41988ecc83a8502a78a792150c5aeecd605bc81d [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 Gowdru6a80bbd2019-07-02 07:36:09 -070094 //TPID constant
95 TPID = "tpid"
96 //IPProto constant
97 IPProto = "ip_proto"
98 //InPort constant
99 InPort = "in_port"
100 //VlanVid constant
101 VlanVid = "vlan_vid"
102 //VlanPcp constant
103 VlanPcp = "vlan_pcp"
104
105 //UDPDst constant
106 UDPDst = "udp_dst"
107 //UDPSrc constant
108 UDPSrc = "udp_src"
109 //Ipv4Dst constant
110 Ipv4Dst = "ipv4_dst"
111 //Ipv4Src constant
112 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700113 //Metadata constant
114 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700115 //TunnelID constant
116 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700117 //Output constant
118 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000119 //GroupID constant
120 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700121 // Actions
122
123 //PopVlan constant
124 PopVlan = "pop_vlan"
125 //PushVlan constant
126 PushVlan = "push_vlan"
127 //TrapToHost constant
128 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400129 //MaxMeterBand constant
130 MaxMeterBand = 2
131 //VlanPCPMask contant
132 VlanPCPMask = 0xFF
133 //VlanvIDMask constant
134 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000135 //IntfID constant
136 IntfID = "intfId"
137 //OnuID constant
138 OnuID = "onuId"
139 //UniID constant
140 UniID = "uniId"
141 //PortNo constant
142 PortNo = "portNo"
143 //AllocID constant
144 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000145 //GemID constant
146 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000147
148 //NoneOnuID constant
149 NoneOnuID = -1
150 //NoneUniID constant
151 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700152
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700153 // Max number of flows that can be queued per ONU
154 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530155
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700156 bitMapPrefix = "0b"
157 pbit1 = '1'
158)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400159
Gamze Abakafee36392019-10-03 11:17:24 +0000160type schedQueue struct {
161 direction tp_pb.Direction
162 intfID uint32
163 onuID uint32
164 uniID uint32
165 tpID uint32
166 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700167 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000168 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400169 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000170}
171
Gamze Abaka7650be62021-02-26 10:50:36 +0000172type flowContext struct {
173 intfID uint32
174 onuID uint32
175 uniID uint32
176 portNo uint32
177 classifier map[string]interface{}
178 action map[string]interface{}
179 logicalFlow *ofp.OfpFlowStats
180 allocID uint32
181 gemPortID uint32
182 tpID uint32
183 pbitToGem map[uint32]uint32
184 gemToAes map[uint32]bool
185}
186
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700187// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
188// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
189// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
190// flow and processes it serially
191type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400192 ctx context.Context // Flow handler context
193 addFlow bool // if true flow to be added, else removed
194 flow *ofp.OfpFlowStats // Flow message
195 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
196 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000197}
198
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700199//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530200type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700201 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700202 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 deviceHandler *DeviceHandler
204 grpMgr *OpenOltGroupMgr
205 resourceMgr *rsrcMgr.OpenOltResourceMgr
206
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700207 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
208 packetInGemPortLock sync.RWMutex
209
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700210 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
211 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700212 incomingFlows []chan flowControlBlock
213 stopFlowHandlerRoutine []chan bool
214 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530215}
216
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700217//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700218func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000219 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530220 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530221 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530222
manikkaraj kbf256be2019-03-25 00:13:48 +0530223 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700224 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700225 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530226 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000227 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
228 if ponPortIdx != dh.totalPonPorts {
229 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
230 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
231 return nil
232 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530233 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530234 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700235
236 // Create a slice of buffered channels for handling concurrent flows per ONU.
237 // 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 -0700238 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
239 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
240 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700241 for i := range flowMgr.incomingFlows {
242 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800243 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700244 // Spin up a go routine to handling incoming flows (add/remove).
245 // There will be on go routine per ONU.
246 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700247 flowMgr.flowHandlerRoutineActive[i] = true
248 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700249 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700250
Esin Karamanccb714b2019-11-29 15:02:06 +0000251 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700252 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000253 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530254 return &flowMgr
255}
256
Kent Hagermane6ff1012020-07-14 15:07:53 -0400257func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000258 // In case of nni trap flow
259 if deviceFlow.AccessIntfId == -1 {
260 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.AccessIntfId), flowFromCore)
261 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
263 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin sapli9e4c5092022-02-01 13:52:33 +0000264 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700265 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
266 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
267 for _, gemPort := range deviceFlow.PbitToGemport {
yasin sapli9e4c5092022-02-01 13:52:33 +0000268 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700269 return err
270 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700271 }
Gamze Abakafee36392019-10-03 11:17:24 +0000272 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700273 return nil
274}
275
Girish Gowdra9602eb42020-09-09 15:50:39 -0700276func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000277 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400278 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000279 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530280 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700281 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530282
Neha Sharma96b7bf22020-06-15 10:37:32 +0000283 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530284 "device-id": f.deviceHandler.device.Id,
285 "intf-id": intfID,
286 "onu-id": onuID,
287 "uni-id": uniID,
288 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700289 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530290 "action": actionInfo,
291 "usmeter-iD": UsMeterID,
292 "dsmeter-iD": DsMeterID,
293 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400294 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
295 // is because the flow is an NNI flow and there would be no onu resources associated with it
296 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400297 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200298 cause := "no-onu-id-for-flow"
299 fields := log.Fields{
300 "onu": onuID,
301 "port-no": portNo,
302 "classifer": classifierInfo,
303 "action": actionInfo,
304 "device-id": f.deviceHandler.device.Id}
305 logger.Errorw(ctx, cause, fields)
306 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530307 }
308
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700309 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000310 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530311 "uni": uni,
312 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530313
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700314 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
315 "device-id": f.deviceHandler.device.Id,
316 "intf-id": intfID,
317 "onu-id": onuID,
318 "uni-id": uniID,
319 "port-no": portNo,
320 "classifier": classifierInfo,
321 "action": actionInfo,
322 "usmeter-id": UsMeterID,
323 "dsmeter-id": DsMeterID,
324 "tp-id": TpID})
325 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
326 if allocID == 0 || gemPorts == nil || TpInst == nil {
327 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
328 return olterrors.NewErrNotFound(
329 "alloc-id-gem-ports-tp-unavailable",
330 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400331 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700332 args := make(map[string]uint32)
333 args[IntfID] = intfID
334 args[OnuID] = onuID
335 args[UniID] = uniID
336 args[PortNo] = portNo
337 args[AllocID] = allocID
338
339 /* Flows can be added specific to gemport if p-bits are received.
340 * If no pbit mentioned then adding flows for all gemports
341 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000342 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530343}
344
salmansiddiqui7ac62132019-08-22 03:58:50 +0000345// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800346// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530347func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400348
Girish Gowdraf3728b12022-02-02 21:46:51 -0800349 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530350 log.Fields{"dir": sq.direction,
351 "intf-id": sq.intfID,
352 "onu-id": sq.onuID,
353 "uni-id": sq.uniID,
354 "tp-id": sq.tpID,
355 "meter-id": sq.meterID,
356 "tp-inst": sq.tpInst,
357 "flowmetadata": sq.flowMetadata,
358 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400359
Girish Gowdra6071f382021-12-14 12:52:04 +0530360 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000361 if err != nil {
362 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400363 }
364
Girish Gowdraf3728b12022-02-02 21:46:51 -0800365 var TrafficShaping *tp_pb.TrafficShapingInfo
366 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
367 return olterrors.NewErrInvalidValue(log.Fields{
368 "reason": "invalid-meter-config",
369 "meter-id": sq.meterID,
370 "device-id": f.deviceHandler.device.Id}, nil)
371 }
372
373 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
374 return olterrors.NewErrInvalidValue(log.Fields{
375 "reason": "invalid-meter-config",
376 "meter-id": sq.meterID,
377 "device-id": f.deviceHandler.device.Id}, nil)
378 }
379
380 var SchedCfg *tp_pb.SchedulerConfig
381 if sq.direction == tp_pb.Direction_UPSTREAM {
382 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
383 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
384 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
385 }
386 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
387 TrafficSched[0].TechProfileId = sq.tpID
388
Manikkaraj kb1d51442019-07-23 10:41:02 -0400389 /* Lets make a simple assumption that if the meter-id is present on the KV store,
390 * then the scheduler and queues configuration is applied on the OLT device
391 * in the given direction.
392 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530393 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400394 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530395 return olterrors.NewErrNotFound("meter",
396 log.Fields{"intf-id": sq.intfID,
397 "onu-id": sq.onuID,
398 "uni-id": sq.uniID,
399 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400400 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000401
Girish Gowdraf3728b12022-02-02 21:46:51 -0800402 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530403 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800404 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530405 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
Girish Gowdraf3728b12022-02-02 21:46:51 -0800406 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
407 return err
408 }
409
410 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
411 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
412 // Just create gem ports and traffic queues on the current uni for the given service
413 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
414 log.Fields{"intf-id": sq.intfID,
415 "onu-id": sq.onuID,
416 "uni-id": sq.uniID,
417 "tp-id": sq.tpID,
418 "device-id": f.deviceHandler.device.Id})
419 // The upstream scheduler is already created. We only need to create the queues
420 // If there are multiple upstream flows on a given uni, then it is possible that
421 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
422 // TODO: Find better mechanism to not duplicate request.
423 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
424 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
425 log.Fields{"intf-id": sq.intfID,
426 "direction": sq.direction,
427 "device-id": f.deviceHandler.device.Id}, err)
428 }
429 } else {
430 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
431 log.Fields{"intf-id": sq.intfID,
432 "onu-id": sq.onuID,
433 "uni-id": sq.uniID,
434 "tp-id": sq.tpID,
435 "device-id": f.deviceHandler.device.Id})
436 }
437 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400438 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000439
Neha Sharma96b7bf22020-06-15 10:37:32 +0000440 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530441 log.Fields{
442 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530443 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530444 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000445
Girish Gowdraa482f272021-03-24 23:04:19 -0700446 found := false
447 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000448 if sq.flowMetadata != nil {
449 for _, meter := range sq.flowMetadata.Meters {
450 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700451 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700452 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 +0000453 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700454 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530455 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700456 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400457 break
458 }
459 }
460 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000461 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700463 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530464 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800465 "reason": "Could-not-get-meterbands-from-flowMetadata",
466 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "meter-id": sq.meterID,
468 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
Gamze Abaka01174422021-03-10 06:55:27 +0000470
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700471 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530472 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
473 log.Fields{"intf-id": sq.intfID,
474 "direction": sq.direction,
475 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400476 }
477
salmansiddiqui7ac62132019-08-22 03:58:50 +0000478 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 * store the meter id on the KV store, for further reference.
480 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530481 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530482 return olterrors.NewErrAdapter("failed-updating-meter-id",
483 log.Fields{"onu-id": sq.onuID,
484 "meter-id": sq.meterID,
485 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400486 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000487 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530488 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700489 "meter-info": meterInfo,
490 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 return nil
492}
493
Girish Gowdraf3728b12022-02-02 21:46:51 -0800494func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
495 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
496 if err != nil {
497 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
498 log.Fields{"intf-id": sq.intfID,
499 "direction": sq.direction,
500 "device-id": f.deviceHandler.device.Id}, err)
501 }
502 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
503 log.Fields{"direction": sq.direction,
504 "traffic-queues": trafficQueues,
505 "device-id": f.deviceHandler.device.Id})
506 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
507 UniId: sq.uniID, PortNo: sq.uniPort,
508 TrafficQueues: trafficQueues,
509 TechProfileId: TrafficSched[0].TechProfileId}
510 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
511 if len(queues.TrafficQueues) > 1 {
512 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
513 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
514 }
515 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
516 }
517 return err
518}
519
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700520func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700521 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000522
523 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530524 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
525 log.Fields{"intf-id": sq.intfID,
526 "direction": sq.direction,
527 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000528 }
529
Gamze Abakacb0e6772021-06-10 08:32:12 +0000530 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
531 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
532 log.Fields{
533 "direction": sq.direction,
534 "TrafficScheds": TrafficSched,
535 "device-id": f.deviceHandler.device.Id,
536 "intfID": sq.intfID,
537 "onuID": sq.onuID,
538 "uniID": sq.uniID})
539 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
540 IntfId: sq.intfID, OnuId: sq.onuID,
541 UniId: sq.uniID, PortNo: sq.uniPort,
542 TrafficScheds: TrafficSched}); err != nil {
543 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
544 }
545 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
546 "direction": sq.direction,
547 "traffic-queues": trafficQueues,
548 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000549 }
550
551 // On receiving the CreateTrafficQueues request, the driver should create corresponding
552 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000553 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530554 log.Fields{"direction": sq.direction,
555 "traffic-queues": trafficQueues,
556 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000557 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
558 UniId: sq.uniID, PortNo: sq.uniPort,
559 TrafficQueues: trafficQueues,
560 TechProfileId: TrafficSched[0].TechProfileId}
561 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
562 if len(queues.TrafficQueues) > 1 {
563 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
564 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
565 }
566 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530567 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000568 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000569 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530570 "direction": sq.direction,
571 "traffic-queues": trafficQueues,
572 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000573
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700575 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700577 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 +0000578 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
579 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000580 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000581 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700582 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 gemPortID: multicastQueuePerPonPort.GemportId,
584 servicePriority: multicastQueuePerPonPort.Priority,
585 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700586 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000587 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400588 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700589 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400590 return err
591 }
Shrey Baid26912972020-04-16 21:02:31 +0530592
Neha Sharma96b7bf22020-06-15 10:37:32 +0000593 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000594 }
595 }
596 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000597 return nil
598}
599
Girish Gowdraf3728b12022-02-02 21:46:51 -0800600// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
601func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
602 var err error
603 logger.Infow(ctx, "removing-queue-in-olt",
604 log.Fields{
605 "direction": sq.direction,
606 "intf-id": sq.intfID,
607 "onu-id": sq.onuID,
608 "uni-id": sq.uniID,
609 "uni-port": sq.uniPort,
610 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400611
Girish Gowdraf3728b12022-02-02 21:46:51 -0800612 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
613 if err != nil {
614 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
615 log.Fields{
616 "intf-id": sq.intfID,
617 "direction": sq.direction,
618 "device-id": f.deviceHandler.device.Id}, err)
619 }
620
621 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
622 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
623 UniId: sq.uniID, PortNo: sq.uniPort,
624 TrafficQueues: TrafficQueues,
625 TechProfileId: sq.tpID}); err != nil {
626 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
627 log.Fields{
628 "intf-id": sq.intfID,
629 "traffic-queues": TrafficQueues,
630 "device-id": f.deviceHandler.device.Id}, err)
631 }
632 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
633
634 return err
635}
636
637// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
638func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639 var Direction string
640 var SchedCfg *tp_pb.SchedulerConfig
641 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800642 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530643 log.Fields{
644 "direction": sq.direction,
645 "intf-id": sq.intfID,
646 "onu-id": sq.onuID,
647 "uni-id": sq.uniID,
648 "uni-port": sq.uniPort,
649 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000650 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700651 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400652 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000653 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700654 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400655 Direction = "downstream"
656 }
657
Girish Gowdraa482f272021-03-24 23:04:19 -0700658 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 -0400659
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700660 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000661 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000662
Girish Gowdraf3728b12022-02-02 21:46:51 -0800663 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
664 IntfId: sq.intfID, OnuId: sq.onuID,
665 UniId: sq.uniID, PortNo: sq.uniPort,
666 TrafficScheds: TrafficSched}); err != nil {
667 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530668 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800669 "intf-id": sq.intfID,
670 "traffic-schedulers": TrafficSched,
671 "onu-id": sq.onuID,
672 "uni-id": sq.uniID,
673 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000674 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675
Girish Gowdraf3728b12022-02-02 21:46:51 -0800676 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
677 log.Fields{"device-id": f.deviceHandler.device.Id,
678 "intf-id": sq.intfID,
679 "onu-id": sq.onuID,
680 "uni-id": sq.uniID,
681 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400682
Girish Gowdraf3728b12022-02-02 21:46:51 -0800683 if sq.direction == tp_pb.Direction_UPSTREAM {
684 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
685 // Delete the TCONT on the ONU.
686 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
687 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
688 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
689 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000690 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800691 "intf": sq.intfID,
692 "onu-id": sq.onuID,
693 "uni-id": sq.uniID,
694 "device-id": f.deviceHandler.device.Id,
695 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000696 }
697 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000698
699 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400700 * delete the meter id on the KV store.
701 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800702 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400703 return err
704}
705
Girish Gowdra197acc12021-08-16 10:59:45 -0700706// We are trying to force remove the schedulers and queues here if one exists for the given key.
707// We ignore any errors encountered in the process. The errors most likely are encountered when
708// the schedulers and queues are already cleared for the given key.
709func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
710
711 var schedCfg *tp_pb.SchedulerConfig
712 var err error
713 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
714 log.Fields{
715 "direction": sq.direction,
716 "intf-id": sq.intfID,
717 "onu-id": sq.onuID,
718 "uni-id": sq.uniID,
719 "uni-port": sq.uniPort,
720 "tp-id": sq.tpID,
721 "device-id": f.deviceHandler.device.Id})
722 if sq.direction == tp_pb.Direction_UPSTREAM {
723 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
724 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
725 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
726 }
727
728 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
729 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
730 TrafficSched[0].TechProfileId = sq.tpID
731
732 // Remove traffic queues. Ignore any errors, just log them.
733 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
734 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
735 "direction": sq.direction,
736 "intf-id": sq.intfID,
737 "onu-id": sq.onuID,
738 "uni-id": sq.uniID,
739 "uni-port": sq.uniPort,
740 "tp-id": sq.tpID,
741 "device-id": f.deviceHandler.device.Id,
742 "err": err})
743 } else {
744 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
745 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
746 UniId: sq.uniID, PortNo: sq.uniPort,
747 TrafficQueues: TrafficQueues,
748 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
749 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
750 "direction": sq.direction,
751 "intf-id": sq.intfID,
752 "onu-id": sq.onuID,
753 "uni-id": sq.uniID,
754 "uni-port": sq.uniPort,
755 "tp-id": sq.tpID,
756 "device-id": f.deviceHandler.device.Id,
757 "err": err})
758
759 } else {
760 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
761 "direction": sq.direction,
762 "intf-id": sq.intfID,
763 "onu-id": sq.onuID,
764 "uni-id": sq.uniID,
765 "uni-port": sq.uniPort,
766 "tp-id": sq.tpID})
767 }
768 }
769
770 // Remove traffic schedulers. Ignore any errors, just log them.
771 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
772 IntfId: sq.intfID, OnuId: sq.onuID,
773 UniId: sq.uniID, PortNo: sq.uniPort,
774 TrafficScheds: TrafficSched}); err != nil {
775 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
776 "direction": sq.direction,
777 "intf-id": sq.intfID,
778 "onu-id": sq.onuID,
779 "uni-id": sq.uniID,
780 "uni-port": sq.uniPort,
781 "tp-id": sq.tpID,
782 "device-id": f.deviceHandler.device.Id,
783 "err": err})
784 } else {
785 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
786 "direction": sq.direction,
787 "intf-id": sq.intfID,
788 "onu-id": sq.onuID,
789 "uni-id": sq.uniID,
790 "uni-port": sq.uniPort,
791 "tp-id": sq.tpID})
792 }
793}
794
Gamze Abakafee36392019-10-03 11:17:24 +0000795// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400796func (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 +0000797 var allocIDs []uint32
798 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530799 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530800 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000801 var err error
npujarec5762e2020-01-01 14:08:48 +0530802 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
803 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000804 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530805
Neha Sharma96b7bf22020-06-15 10:37:32 +0000806 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530807 "intf-id": intfID,
808 "onu-id": onuID,
809 "uni-id": uniID,
810 "device-id": f.deviceHandler.device.Id,
811 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530812
Manikkaraj kb1d51442019-07-23 10:41:02 -0400813 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700814 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000815 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530817 log.Fields{
818 "path": tpPath,
819 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700820 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000821 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530822 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000823 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530824 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700825 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530826 "tp-id": TpID,
827 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000828 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530829 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400830 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700831 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400832 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530833 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000834 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530835 log.Fields{
836 "uni": uni,
837 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530838 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530839 }
Gamze Abakafee36392019-10-03 11:17:24 +0000840
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700842 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 if UsMeterID != 0 {
844 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
845 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
846 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000847 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700848 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700849 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700850 "onu-id": onuID,
851 "uni-id": uniID,
852 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700853 "meter-id": UsMeterID,
854 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000855 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700856 return 0, nil, nil
857 }
858 }
859 if DsMeterID != 0 {
860 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
861 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
862 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000863 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700864 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700865 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700866 "onu-id": onuID,
867 "uni-id": uniID,
868 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 "meter-id": DsMeterID,
870 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000871 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700872 return 0, nil, nil
873 }
874 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700875 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700876 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700879 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000880
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 if tpInstanceExists {
882 return allocID, gemPortIDs, techProfileInstance
883 }
884
885 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700886 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000888 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700890 "intf-id": intfID,
891 "onu-id": onuID,
892 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 "alloc-ids": allocIDs,
894 "gemports": allgemPortIDs,
895 "device-id": f.deviceHandler.device.Id})
896 // Send Tconts and GEM ports to KV store
897 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530898 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400899 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900 // CreateSchedulerQueues for EPON needs to be implemented here
901 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700902 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700903 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700906 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907
908 if tpInstanceExists {
909 return allocID, gemPortIDs, techProfileInstance
910 }
911
912 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700913 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700914 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000915 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 log.Fields{
917 "alloc-ids": allocIDs,
918 "gemports": allgemPortIDs,
919 "device-id": f.deviceHandler.device.Id})
920 // Send Tconts and GEM ports to KV store
921 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
922 return allocID, gemPortIDs, techProfileInstance
923 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700925 log.Fields{
926 "tpInst": tpInst})
927 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530928 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530929}
930
npujarec5762e2020-01-01 14:08:48 +0530931func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530932
Neha Sharma96b7bf22020-06-15 10:37:32 +0000933 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530934 log.Fields{
935 "intf-id": intfID,
936 "onu-id": onuID,
937 "uni-id": uniID,
938 "alloc-id": allocID,
939 "gemport-ids": gemPortIDs,
940 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530941 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530942 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000943 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 +0530944 }
npujarec5762e2020-01-01 14:08:48 +0530945 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000946 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 +0530947 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700948
Neha Sharma96b7bf22020-06-15 10:37:32 +0000949 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 -0400950 for _, gemPort := range gemPortIDs {
yasin sapli9e4c5092022-02-01 13:52:33 +0000951 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort); err != nil {
952 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
953 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400954 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530955}
956
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700957func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530958 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000959 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700960 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
961 var err error
962 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
963 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
964 if err != nil || f.techprofile == nil {
965 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
966 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
967 }
968 logger.Debugw(ctx, "init-tech-profile-done",
969 log.Fields{
970 "intf-id": intfID,
971 "device-id": f.deviceHandler.device.Id})
972 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700973 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530974 }
975 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700976 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
977 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 +0530978}
979
Gamze Abaka7650be62021-02-26 10:50:36 +0000980func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530981 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000982 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530983 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000984 "uplinkClassifier": flowContext.classifier,
985 "uplinkAction": flowContext.action})
986 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530987 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530988}
989
Gamze Abaka7650be62021-02-26 10:50:36 +0000990func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
991 downlinkClassifier := flowContext.classifier
992 downlinkAction := flowContext.action
993
Andrea Campanellafaa42152021-10-28 11:50:56 +0530994 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
995 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
996 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
997 // Need a better way for detection of packet tag type from OpenFlow message.
998 if _, ok := downlinkClassifier[VlanVid]; !ok {
999 downlinkClassifier[PacketTagType] = SingleTag
1000 } else {
1001 downlinkClassifier[PacketTagType] = DoubleTag
1002 downlinkAction[PopVlan] = true
1003 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001004 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301005 log.Fields{
1006 "downlinkClassifier": downlinkClassifier,
1007 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001008 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1009 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1010 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001011 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001012 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001013 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301014 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001015 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301016 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001017 "onu-id": flowContext.onuID,
1018 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001019 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001020 }
1021 }
1022 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301023 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001024
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001025 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1026 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301027 if ok {
1028 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301029 }
1030
Gamze Abaka7650be62021-02-26 10:50:36 +00001031 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301032}
1033
Gamze Abaka7650be62021-02-26 10:50:36 +00001034func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001035
Gamze Abaka7650be62021-02-26 10:50:36 +00001036 intfID := flowContext.intfID
1037 onuID := flowContext.onuID
1038 uniID := flowContext.uniID
1039 classifier := flowContext.classifier
1040 action := flowContext.action
1041 allocID := flowContext.allocID
1042 gemPortID := flowContext.gemPortID
1043 tpID := flowContext.tpID
1044 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301046 log.Fields{
1047 "intf-id": intfID,
1048 "onu-id": onuID,
1049 "uni-id": uniID,
1050 "device-id": f.deviceHandler.device.Id,
1051 "classifier": classifier,
1052 "action": action,
1053 "direction": direction,
1054 "alloc-id": allocID,
1055 "gemport-id": gemPortID,
1056 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001057
yasin saplid0566272021-12-21 09:10:30 +00001058 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), logicalFlow.Id)
1059 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301061 log.Fields{
1062 "device-id": f.deviceHandler.device.Id,
1063 "intf-id": intfID,
1064 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 return nil
yasin saplid0566272021-12-21 09:10:30 +00001066 } else if err != nil {
1067 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1068 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1069 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301070 }
yasin saplid0566272021-12-21 09:10:30 +00001071
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 classifierProto, err := makeOpenOltClassifierField(classifier)
1073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "classifier": *classifierProto,
1079 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001080 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "action": *actionProto,
1087 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 log.Fields{
1092 "classifier": classifier,
1093 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301094 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301096 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001099 OnuId: int32(onuID),
1100 UniId: int32(uniID),
1101 FlowId: logicalFlow.Id,
1102 FlowType: direction,
1103 AllocId: int32(allocID),
1104 NetworkIntfId: int32(networkIntfID),
1105 GemportId: int32(gemPortID),
1106 Classifier: classifierProto,
1107 Action: actionProto,
1108 Priority: int32(logicalFlow.Priority),
1109 Cookie: logicalFlow.Cookie,
1110 PortNo: flowContext.portNo,
1111 TechProfileId: tpID,
1112 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1113 PbitToGemport: flowContext.pbitToGem,
1114 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001115 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301120 log.Fields{"direction": direction,
1121 "device-id": f.deviceHandler.device.Id,
1122 "flow": flow,
1123 "intf-id": intfID,
1124 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301127}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128
Gamze Abaka7650be62021-02-26 10:50:36 +00001129func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1130
1131 intfID := flowContext.intfID
1132 onuID := flowContext.onuID
1133 uniID := flowContext.uniID
1134 logicalFlow := flowContext.logicalFlow
1135 classifier := flowContext.classifier
1136 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301139 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301142 "action": action,
1143 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
1147 // Clear the action map
1148 for k := range action {
1149 delete(action, k)
1150 }
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 action[TrapToHost] = true
1153 classifier[UDPSrc] = uint32(68)
1154 classifier[UDPDst] = uint32(67)
1155 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
yasin saplid0566272021-12-21 09:10:30 +00001157 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), logicalFlow.Id)
1158 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301160 log.Fields{
1161 "device-id": f.deviceHandler.device.Id,
1162 "intf-id": intfID,
1163 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 return nil
yasin saplid0566272021-12-21 09:10:30 +00001165 } else if err != nil {
1166 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1167 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1168 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301169 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "ul_classifier": classifier,
1174 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "intf-id": intfID,
1177 "onu-id": onuID,
1178 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 classifierProto, err := makeOpenOltClassifierField(classifier)
1181 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301182 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001185 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301187 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 }
1189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 OnuId: int32(onuID),
1192 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001194 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001195 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001197 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198 Classifier: classifierProto,
1199 Action: actionProto,
1200 Priority: int32(logicalFlow.Priority),
1201 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 PortNo: flowContext.portNo,
1203 TechProfileId: flowContext.tpID,
1204 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1205 PbitToGemport: flowContext.pbitToGem,
1206 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001207 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001214 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301215 "intf-id": intfID,
1216 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301217
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301219}
1220
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001222func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1223 delete(flowContext.classifier, VlanVid)
1224 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225}
1226
1227//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001228func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1229
1230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
yasin saplid0566272021-12-21 09:10:30 +00001255 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), logicalFlow.Id)
1256 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
yasin saplid0566272021-12-21 09:10:30 +00001259 } else if err != nil {
1260 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1261 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1262 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "ul_classifier": classifier,
1268 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301270 "device-id": f.deviceHandler.device.Id,
1271 "intf-id": intfID,
1272 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 classifierProto, err := makeOpenOltClassifierField(classifier)
1275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "classifier": *classifierProto,
1281 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001282 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301284 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 }
1286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 OnuId: int32(onuID),
1289 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001292 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 Classifier: classifierProto,
1296 Action: actionProto,
1297 Priority: int32(logicalFlow.Priority),
1298 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 PortNo: flowContext.portNo,
1300 TechProfileId: flowContext.tpID,
1301 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1302 PbitToGemport: flowContext.pbitToGem,
1303 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001340 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
yasin saplid0566272021-12-21 09:10:30 +00001346 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), logicalFlow.Id)
1347 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301349 "device-id": f.deviceHandler.device.Id,
1350 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 "intf-id": intfID,
1352 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
yasin saplid0566272021-12-21 09:10:30 +00001354 } else if err != nil {
1355 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1356 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1357 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301358 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001359 //Add Uplink EthType Flow
1360 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "ul_classifier": uplinkClassifier,
1363 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "intf-id": intfID,
1367 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1370 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301371 return olterrors.NewErrInvalidValue(log.Fields{
1372 "classifier": uplinkClassifier,
1373 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "classifier": *classifierProto,
1378 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001379 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301381 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "action": *actionProto,
1386 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301391 "action": action,
1392 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 }
1395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 OnuId: int32(onuID),
1398 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001399 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 AllocId: int32(allocID),
1402 NetworkIntfId: int32(networkIntfID),
1403 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 Classifier: classifierProto,
1405 Action: actionProto,
1406 Priority: int32(logicalFlow.Priority),
1407 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001409 TechProfileId: flowContext.tpID,
1410 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1411 PbitToGemport: flowContext.pbitToGem,
1412 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301418 log.Fields{
1419 "device-id": f.deviceHandler.device.Id,
1420 "onu-id": onuID,
1421 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001422 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301423 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301439 // 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 -07001440 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1441 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301442 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1443 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1444 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1445 // becomes the IVid.
1446 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1447 if vid != ReservedVlan {
1448 classifier.IVid = vid
1449 }
1450 } else {
1451 if vid != ReservedVlan {
1452 classifier.OVid = vid
1453 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001454 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301455 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301456 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001457 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301458 classifier.OPbits = vlanPcp
1459 } else {
1460 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001462 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1463 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1464 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1465 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001466 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001467 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1468 classifier.PktTagType = pktTagType
1469
1470 switch pktTagType {
1471 case SingleTag:
1472 case DoubleTag:
1473 case Untagged:
1474 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001475 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301476 }
1477 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001478 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301479}
1480
Gamze Abaka724d0852020-03-18 12:10:24 +00001481func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001482 var actionCmd openoltpb2.ActionCmd
1483 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301484 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001485 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301486 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001487 if _, ok := actionInfo[VlanPcp]; ok {
1488 action.Cmd.RemarkInnerPbits = true
1489 action.IPbits = actionInfo[VlanPcp].(uint32)
1490 if _, ok := actionInfo[VlanVid]; ok {
1491 action.Cmd.TranslateInnerTag = true
1492 action.IVid = actionInfo[VlanVid].(uint32)
1493 }
1494 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001495 } else if _, ok := actionInfo[PushVlan]; ok {
1496 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301497 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001498 if _, ok := actionInfo[VlanPcp]; ok {
1499 action.OPbits = actionInfo[VlanPcp].(uint32)
1500 action.Cmd.RemarkOuterPbits = true
1501 if _, ok := classifierInfo[VlanVid]; ok {
1502 action.IVid = classifierInfo[VlanVid].(uint32)
1503 action.Cmd.TranslateInnerTag = true
1504 }
1505 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001506 } else if _, ok := actionInfo[TrapToHost]; ok {
1507 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301508 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301509 // When OLT is transparent to vlans no-action is valid.
1510 /*
1511 else {
1512 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1513 }
1514 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001515 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301516}
1517
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001518// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001519func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001520 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301521}
1522
Gamze Abakafee36392019-10-03 11:17:24 +00001523// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001524// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1525// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1526// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1527// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1528// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1529// because it was observed that if the ONU device was deleted too soon after the flows were
1530// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1531// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1532// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001533func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301534 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001535 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1536
Gamze Abakafee36392019-10-03 11:17:24 +00001537 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001538
1539 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001540 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001541 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1542 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1543 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1544 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1545 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1546 log.Fields{
1547 "tp-id": tpID,
1548 "path": tpPath})
1549 }
1550 switch tpInstance := tpInst.(type) {
1551 case *tp_pb.TechProfileInstance:
1552 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1553 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1554 }
1555 // Force cleanup scheduler/queues -- end
1556
1557 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301558 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001559 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301560 // return err
1561 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001562 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001563 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 +00001564 }
1565 return nil
1566}
1567
1568// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301569func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001570 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001571 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001572 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001573 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301574 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1575 log.Fields{
1576 "tp-id": tpID,
1577 "uni-port-name": uniPortName,
1578 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001579 }
1580 return nil
1581}
1582
David K. Bainbridge794735f2020-02-11 21:01:37 -08001583func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001584
1585 var intfID uint32
1586 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1587 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1588 */
1589 if deviceFlow.AccessIntfId != -1 {
1590 intfID = uint32(deviceFlow.AccessIntfId)
1591 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001592 // We need to log the valid interface ID.
1593 // 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 +00001594 intfID = uint32(deviceFlow.NetworkIntfId)
1595 }
1596
Neha Sharma96b7bf22020-06-15 10:37:32 +00001597 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301598 "flow": *deviceFlow,
1599 "device-id": f.deviceHandler.device.Id,
1600 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001601 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001602
1603 st, _ := status.FromError(err)
1604 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001605 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001606 "err": err,
1607 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301608 "device-id": f.deviceHandler.device.Id,
1609 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301611 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001612
1613 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301615 log.Fields{"err": err,
1616 "device-flow": deviceFlow,
1617 "device-id": f.deviceHandler.device.Id,
1618 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001619 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001620 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001621 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301622 log.Fields{
1623 "flow": *deviceFlow,
1624 "device-id": f.deviceHandler.device.Id,
1625 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001626
yasin saplid0566272021-12-21 09:10:30 +00001627 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1628 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1629 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001630 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001632}
1633
Neha Sharma96b7bf22020-06-15 10:37:32 +00001634func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1635 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301636 log.Fields{
1637 "flow": *deviceFlow,
1638 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001639 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001640 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001641 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301643 log.Fields{
1644 "err": err,
1645 "deviceFlow": deviceFlow,
1646 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001647 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001649 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001650 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001651
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001652 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001653 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001654 "of-flow-id": ofFlowID,
1655 "flow": *deviceFlow,
1656 "device-id": f.deviceHandler.device.Id,
1657 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301659}
1660
David K. Bainbridge794735f2020-02-11 21:01:37 -08001661func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001662
1663 classifierInfo := make(map[string]interface{})
1664 actionInfo := make(map[string]interface{})
1665
1666 classifierInfo[EthType] = uint32(LldpEthType)
1667 classifierInfo[PacketTagType] = Untagged
1668 actionInfo[TrapToHost] = true
1669
1670 // LLDP flow is installed to trap LLDP packets on the NNI port.
1671 // We manage flow_id resource pool on per PON port basis.
1672 // Since this situation is tricky, as a hack, we pass the NNI port
1673 // index (network_intf_id) as PON port Index for the flow_id resource
1674 // pool. Also, there is no ONU Id available for trapping LLDP packets
1675 // on NNI port, use onu_id as -1 (invalid)
1676 // ****************** CAVEAT *******************
1677 // This logic works if the NNI Port Id falls within the same valid
1678 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1679 // we need to have a re-look at this.
1680 // *********************************************
1681
1682 var onuID = -1
1683 var uniID = -1
1684 var gemPortID = -1
1685
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001686 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001687 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301688 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001689 }
yasin saplid0566272021-12-21 09:10:30 +00001690
1691 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, f.ponPortIdx, int32(onuID), flow.Id)
1692 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001693 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001694 return nil
yasin saplid0566272021-12-21 09:10:30 +00001695 } else if err != nil {
1696 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1697 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1698 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001699 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001700
David K. Bainbridge794735f2020-02-11 21:01:37 -08001701 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1702 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301703 return olterrors.NewErrInvalidValue(
1704 log.Fields{
1705 "classifier": classifierInfo,
1706 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001707 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001708 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301709 log.Fields{
1710 "classifier": *classifierProto,
1711 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001712 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001713 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301714 return olterrors.NewErrInvalidValue(
1715 log.Fields{
1716 "action": actionInfo,
1717 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001718 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301720 log.Fields{
1721 "action": *actionProto,
1722 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001723
1724 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1725 OnuId: int32(onuID), // OnuId not required
1726 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001727 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001728 FlowType: Downstream,
1729 NetworkIntfId: int32(networkInterfaceID),
1730 GemportId: int32(gemPortID),
1731 Classifier: classifierProto,
1732 Action: actionProto,
1733 Priority: int32(flow.Priority),
1734 Cookie: flow.Cookie,
1735 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001737 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301738 log.Fields{
1739 "flow": downstreamflow,
1740 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001741 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001742 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301743 log.Fields{
1744 "device-id": f.deviceHandler.device.Id,
1745 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001746 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001747
David K. Bainbridge794735f2020-02-11 21:01:37 -08001748 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301749}
1750
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001751func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1752 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001753}
1754
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001755//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001757 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1758 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1759 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001760 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301761 log.Fields{
1762 "intf-id": intfID,
1763 "onu-id": onuID,
1764 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001766 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301767 return nil, olterrors.NewErrNotFound("onu-child-device",
1768 log.Fields{
1769 "onu-id": onuID,
1770 "intf-id": intfID,
1771 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001772 }
khenaidoo106c61a2021-08-11 18:05:46 -04001773 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 -07001774 //better to ad the device to cache here.
1775 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1776 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001777 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301778 log.Fields{
1779 "intf-id": intfID,
1780 "onu-id": onuID,
1781 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001782 }
1783
1784 return onuDev.(*OnuDevice), nil
1785}
1786
1787//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1789 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301790 log.Fields{
1791 "pon-port": intfID,
1792 "onu-id": onuID,
1793 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001794 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001795 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001796 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301797 return nil, olterrors.NewErrNotFound("onu",
1798 log.Fields{
1799 "interface-id": parentPortNo,
1800 "onu-id": onuID,
1801 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001802 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301803 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301805 log.Fields{
1806 "device-id": f.deviceHandler.device.Id,
1807 "child_device_id": onuDevice.Id,
1808 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301809 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301810}
1811
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1813 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301814 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001815 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301816 log.Fields{
1817 "intf-id": intfID,
1818 "onu-id": onuID,
1819 "uni-id": uniID,
1820 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001821 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301822 }
1823
khenaidoodc2116e2021-10-19 17:33:19 -04001824 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001825 DeviceId: onuDev.deviceID,
1826 UniId: uniID,
1827 TpInstancePath: tpPath,
1828 GemPortId: gemPortID,
1829 }
1830 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1831
1832 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301833 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1834 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001835 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1836 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301837 "onu-id": onuDev.deviceID,
1838 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001839 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301840 }
khenaidoo106c61a2021-08-11 18:05:46 -04001841
Neha Sharma96b7bf22020-06-15 10:37:32 +00001842 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301843 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001844 "msg": delGemPortMsg,
1845 "from-adapter": f.deviceHandler.device.Type,
1846 "to-adapter": onuDev.deviceType,
1847 "device-id": f.deviceHandler.device.Id,
1848 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301849 return nil
1850}
1851
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1853 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301854 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001855 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301856 log.Fields{
1857 "intf-id": intfID,
1858 "onu-id": onuID,
1859 "uni-id": uniID,
1860 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001861 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301862 }
1863
khenaidoodc2116e2021-10-19 17:33:19 -04001864 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001865 DeviceId: onuDev.deviceID,
1866 UniId: uniID,
1867 TpInstancePath: tpPath,
1868 AllocId: allocID,
1869 }
1870
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301872 log.Fields{
1873 "msg": *delTcontMsg,
1874 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001875
1876 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301877 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1878 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001879 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1880 "to-adapter": onuDev.adapterEndpoint,
1881 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301882 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001883 "device-id": f.deviceHandler.device.Id}, err)
1884
Girish Gowdra6b130582019-11-20 16:45:20 +05301885 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001886 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301887 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001888 "msg": delTcontMsg,
1889 "device-id": f.deviceHandler.device.Id,
1890 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301891 return nil
1892}
1893
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301894//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001895// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001896func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001897 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001898
1899 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001900
Girish Gowdraa482f272021-03-24 23:04:19 -07001901 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1902 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001903 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1904 log.Fields{
1905 "tpPath": tpPath,
1906 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001907
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001908 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001909 if err != nil || techprofileInst == nil {
1910 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1911 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1912 if childDevice == nil {
1913 // happens when subscriber un-provision is immediately followed by child device delete
1914 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1915 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1916 return nil
1917 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001918 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1919 log.Fields{
1920 "tp-id": tpID,
1921 "path": tpPath}, err)
1922 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001923
1924 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001925 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001926 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001927 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1928 gemPortID := gemPort.GemportId
yasin sapli9e4c5092022-02-01 13:52:33 +00001929 used := f.resourceMgr.IsGemPortUsedByAnotherFlow(gemPortID, flowID)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001930 if used {
yasin sapli9e4c5092022-02-01 13:52:33 +00001931 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, intfID, gemPortID)
1932 if err != nil {
1933 return err
1934 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001935 for i, flowIDinMap := range flowIDs {
1936 if flowIDinMap == flowID {
1937 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001938 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1939 return err
1940 }
1941 break
1942 }
1943 }
1944 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1945 log.Fields{
1946 "gemport-id": gemPortID,
1947 "usedByFlows": flowIDs,
1948 "currentFlow": flowID,
1949 "device-id": f.deviceHandler.device.Id})
1950 allGemPortsFree = false
1951 }
1952 }
1953 if !allGemPortsFree {
1954 return nil
1955 }
1956 }
1957
1958 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 -08001959
1960 // 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 +00001961 switch techprofileInst := techprofileInst.(type) {
1962 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001963 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
1964 logger.Warn(ctx, err)
1965 }
1966 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1967 logger.Warn(ctx, err)
1968 }
1969
1970 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1971 gemPortID := gemPort.GemportId
Girish Gowdraf3728b12022-02-02 21:46:51 -08001972 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
1973
yasin sapli9e4c5092022-02-01 13:52:33 +00001974 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001975 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1976 log.Fields{
1977 "err": err,
1978 "intf": intfID,
1979 "onu-id": onuID,
1980 "uni-id": uniID,
1981 "device-id": f.deviceHandler.device.Id,
1982 "gemport-id": gemPortID})
1983 }
1984
1985 }
1986 // Remove queues at OLT in upstream and downstream direction
1987 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1988 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1989 logger.Warn(ctx, err)
1990 }
1991 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1992 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1993 logger.Warn(ctx, err)
1994 }
1995 }
1996
1997 switch techprofileInst := techprofileInst.(type) {
1998 case *tp_pb.TechProfileInstance:
1999 // 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 +01002000 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2001 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2002 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002003 // all alloc object references removed, remove upstream scheduler
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002004 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002005 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002006 logger.Warn(ctx, err)
2007 }
2008 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002009 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
2010 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
2011 } else {
2012 // just remove meter reference for the upstream direction for the current pon/onu/uni
2013 // 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
2014 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2015 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002016 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002017 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2018 // but still preserve it on the resource pool.
2019 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
2020 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002021
Girish Gowdraf3728b12022-02-02 21:46:51 -08002022 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2023 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2024 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
2025 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2026 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002027 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002028 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002029 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002030 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002031 logger.Warn(ctx, err)
2032 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002033 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002034 logger.Warn(ctx, err)
2035 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002037 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302039 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002040 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302041 "onu-id": onuID,
2042 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002043 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002044 "alloc-id": techprofileInst.AllocId,
2045 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002046 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002047 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002048 default:
2049 logger.Errorw(ctx, "error-unknown-tech",
2050 log.Fields{
2051 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002052 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002053
2054 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2055 switch techprofileInst := techprofileInst.(type) {
2056 case *tp_pb.TechProfileInstance:
2057 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2058 // Delete the gem port on the ONU.
2059 if sendDeleteGemRequest {
2060 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2061 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2062 log.Fields{
2063 "err": err,
2064 "intfID": intfID,
2065 "onu-id": onuID,
2066 "uni-id": uniID,
2067 "device-id": f.deviceHandler.device.Id,
2068 "gemport-id": gemPort.GemportId})
2069 }
2070 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId)
2071 }
2072 }
2073 }
2074
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302075 return nil
2076}
2077
David K. Bainbridge794735f2020-02-11 21:01:37 -08002078// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002079func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002080 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302081 log.Fields{
2082 "flowDirection": flowDirection,
2083 "flow": *flow,
2084 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002085
2086 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002087 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002088 }
2089
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302090 var ethType, ipProto, inPort uint32
2091 for _, field := range flows.GetOfbFields(flow) {
2092 if field.Type == flows.IP_PROTO {
2093 ipProto = field.GetIpProto()
2094 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2095 } else if field.Type == flows.ETH_TYPE {
2096 ethType = field.GetEthType()
2097 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2098 } else if field.Type == flows.IN_PORT {
2099 inPort = field.GetPort()
2100 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2101 }
2102 }
2103 portType := plt.IntfIDToPortTypeName(inPort)
2104 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2105 (portType == voltha.Port_ETHERNET_NNI) {
2106 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2107 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2108 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2109 // No more processing needed for trap from nni flows.
2110 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302111
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302112 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302113 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002114 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002115 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302116 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002117 onuID := int32(onu)
2118 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002119 tpID, err := getTpIDFromFlow(ctx, flow)
2120 if err != nil {
2121 return olterrors.NewErrNotFound("tp-id",
2122 log.Fields{
2123 "flow": flow,
2124 "intf-id": Intf,
2125 "onu-id": onuID,
2126 "uni-id": uniID,
2127 "device-id": f.deviceHandler.device.Id}, err)
2128 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302129
Neha Sharma96b7bf22020-06-15 10:37:32 +00002130 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302131 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002132 "flow-id": flow.Id,
2133 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302134 "onu-id": onuID,
2135 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302136
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002137 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2138 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002139 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2140 return err
2141 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002142
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002143 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002144 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2145 "flow-id": flow.Id,
2146 "device-id": f.deviceHandler.device.Id,
2147 "onu-id": onuID,
2148 "intf": Intf,
2149 "err": err,
2150 })
2151 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302152 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002153
Girish Gowdra82c80982021-03-26 16:22:02 -07002154 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2155 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2156 return err
2157 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002158 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002159}
2160
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002161//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002162func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002163
Matteo Scandolof16389e2021-05-18 00:47:08 +00002164 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302165 var direction string
2166 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002167
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302168 for _, action := range flows.GetActions(flow) {
2169 if action.Type == flows.OUTPUT {
2170 if out := action.GetOutput(); out != nil {
2171 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002172 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302173 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002175 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002176 }
2177 }
2178 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002179
2180 if flows.HasGroup(flow) {
2181 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002182 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002183 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302184 direction = Upstream
2185 } else {
2186 direction = Downstream
2187 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302188
Girish Gowdracefae192020-03-19 18:14:10 -07002189 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002190 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002191
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002192 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002193}
2194
Esin Karamanae41e2b2019-12-17 18:13:13 +00002195//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2196func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002197 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002198 if ethType, ok := classifierInfo[EthType]; ok {
2199 if ethType.(uint32) == IPv4EthType {
2200 if ipProto, ok := classifierInfo[IPProto]; ok {
2201 if ipProto.(uint32) == IgmpProto {
2202 return true
2203 }
2204 }
2205 }
2206 }
2207 }
2208 return false
2209}
2210
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002211// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002212func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002213 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2214 // The device itself is going to be reset as part of deletion. So nothing to be done.
2215 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2216 return nil
2217 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002218 // Step1 : Fill flowControlBlock
2219 // Step2 : Push the flowControlBlock to ONU channel
2220 // Step3 : Wait on response channel for response
2221 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002222 startTime := time.Now()
2223 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002224 errChan := make(chan error)
2225 flowCb := flowControlBlock{
2226 ctx: ctx,
2227 addFlow: addFlow,
2228 flow: flow,
2229 flowMetadata: flowMetadata,
2230 errChan: &errChan,
2231 }
2232 inPort, outPort := getPorts(flow)
2233 var onuID uint32
2234 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002235 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002236 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002237 if f.flowHandlerRoutineActive[onuID] {
2238 // inPort or outPort is InvalidPort for trap-from-nni flows.
2239 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2240 // Send the flowCb on the ONU flow channel
2241 f.incomingFlows[onuID] <- flowCb
2242 // Wait on the channel for flow handlers return value
2243 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002244 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002245 return err
2246 }
2247 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2248 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002249}
2250
2251// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2252// 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 -07002253func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002254 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002255 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002256 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002257 // block on the channel to receive an incoming flow
2258 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002259 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002260 if flowCb.addFlow {
2261 logger.Info(flowCb.ctx, "adding-flow-start")
2262 startTime := time.Now()
2263 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2264 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2265 // Pass the return value over the return channel
2266 *flowCb.errChan <- err
2267 } else {
2268 logger.Info(flowCb.ctx, "removing-flow-start")
2269 startTime := time.Now()
2270 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2271 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2272 // Pass the return value over the return channel
2273 *flowCb.errChan <- err
2274 }
2275 case <-stopHandler:
2276 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2277 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002278 }
2279 }
2280}
2281
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002282// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002283func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002284 for i, v := range f.stopFlowHandlerRoutine {
2285 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002286 select {
2287 case v <- true:
2288 case <-time.After(time.Second * 5):
2289 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2290 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002291 }
2292 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002293 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002294 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2295}
2296
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002297// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302298// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002299func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002300 classifierInfo := make(map[string]interface{})
2301 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002302 var UsMeterID uint32
2303 var DsMeterID uint32
2304
Neha Sharma96b7bf22020-06-15 10:37:32 +00002305 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302306 log.Fields{
2307 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002308 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002309 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002310
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002312 if err != nil {
2313 // Error logging is already done in the called function
2314 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002315 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302316 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002317
Esin Karamanccb714b2019-11-29 15:02:06 +00002318 if flows.HasGroup(flow) {
2319 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002320 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002321 }
2322
manikkaraj k17652a72019-05-06 09:06:36 -04002323 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002324 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002325 if err != nil {
2326 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002327 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002328 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002329
Neha Sharma96b7bf22020-06-15 10:37:32 +00002330 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302331 log.Fields{
2332 "classifierinfo_inport": classifierInfo[InPort],
2333 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002334 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002335
Humera Kouser94d7a842019-08-25 19:04:32 -04002336 if ethType, ok := classifierInfo[EthType]; ok {
2337 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002338 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002339 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002340 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002341 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002342 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002343 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2344 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2345 }
2346 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002347 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002348 if ipProto, ok := classifierInfo[IPProto]; ok {
2349 if ipProto.(uint32) == IPProtoDhcp {
2350 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302351 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002353 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002354 }
2355 }
2356 }
2357 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002358 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002360 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002361 }
A R Karthick1f85b802019-10-11 05:06:05 +00002362
npujarec5762e2020-01-01 14:08:48 +05302363 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002364
Girish Gowdra6071f382021-12-14 12:52:04 +05302365 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002366 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302367 return olterrors.NewErrNotFound("tpid-for-flow",
2368 log.Fields{
2369 "flow": flow,
2370 "intf-id": IntfID,
2371 "onu-id": onuID,
2372 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002373 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002374 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302375 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302376 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302377 "intf-id": intfID,
2378 "onu-id": onuID,
2379 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002380 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002381 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002382 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302383 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2384 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2385 return err
2386 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002387 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002388 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002389 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302390 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2391 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2392 return err
2393 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002394 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302395 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002396}
Girish Gowdra3d633032019-12-10 16:37:05 +05302397
Esin Karamanccb714b2019-11-29 15:02:06 +00002398// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002399func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302400 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002401 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302402 "classifier-info": classifierInfo,
2403 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002404
Esin Karaman65409d82020-03-18 10:58:18 +00002405 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002406 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002407 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002408 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002409
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002410 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002411
David K. Bainbridge794735f2020-02-11 21:01:37 -08002412 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002413
yasin saplid0566272021-12-21 09:10:30 +00002414 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), flow.Id)
2415 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002417 return nil
yasin saplid0566272021-12-21 09:10:30 +00002418 } else if err != nil {
2419 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2420 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2421 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002422 }
yasin saplid0566272021-12-21 09:10:30 +00002423
David K. Bainbridge794735f2020-02-11 21:01:37 -08002424 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2425 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002426 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002427 }
2428 groupID := actionInfo[GroupID].(uint32)
2429 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002430 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002431 FlowType: Multicast,
2432 NetworkIntfId: int32(networkInterfaceID),
2433 GroupId: groupID,
2434 Classifier: classifierProto,
2435 Priority: int32(flow.Priority),
2436 Cookie: flow.Cookie}
2437
Kent Hagermane6ff1012020-07-14 15:07:53 -04002438 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002439 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002440 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002443 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002444 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002445 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002446 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002447 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002448 //cached group can be removed now
2449 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002450 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002451 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002452 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002453
David K. Bainbridge794735f2020-02-11 21:01:37 -08002454 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002455}
2456
Esin Karaman65409d82020-03-18 10:58:18 +00002457//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2458func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2459 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002460 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002461 if err != nil {
2462 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2463 }
2464 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002465 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002466
2467 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2468 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002469}
2470
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002471//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002472func (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 -07002473
Neha Sharma96b7bf22020-06-15 10:37:32 +00002474 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302475 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302477 log.Fields{
2478 "intf-id": intfID,
2479 "onu-id": onuID,
2480 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002481 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302482 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002483 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002484
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002486 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002487 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002488 UniId: uniID,
2489 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002490 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002491 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002492 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002493
2494 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2495 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302496 return olterrors.NewErrCommunication("send-techprofile-download-request",
2497 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002498 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302499 "to-adapter": onuDev.deviceType,
2500 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002501 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002502 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002503 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302504 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302505}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002506
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002507//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302508func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002509 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002510
2511 if packetIn.IntfType == "pon" {
2512 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002513 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002514 onuID, uniID := packetIn.OnuId, packetIn.UniId
2515 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 +00002516
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002517 if packetIn.PortNo != 0 {
2518 logicalPortNum = packetIn.PortNo
2519 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002520 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002521 }
2522 // 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 +00002523 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002524 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002525 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002526 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002527
2528 if logger.V(log.DebugLevel) {
2529 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2530 log.Fields{
2531 "logical-port-num": logicalPortNum,
2532 "intf-type": packetIn.IntfType,
2533 "packet": hex.EncodeToString(packetIn.Pkt),
2534 })
2535 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002536 return logicalPortNum, nil
2537}
2538
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002539//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002540func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002541 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002542
2543 ctag, priority, err := getCTagFromPacket(ctx, packet)
2544 if err != nil {
2545 return 0, err
2546 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302547
Esin Karaman7fb80c22020-07-16 14:23:33 +00002548 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002549 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002550 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002551 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002552 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302553 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002554 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302555 log.Fields{
2556 "pktinkey": pktInkey,
2557 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002558
2559 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002560 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302561 //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 +00002562 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302563 if err == nil {
2564 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002565 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302566 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002567 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002568 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302569 log.Fields{
2570 "pktinkey": pktInkey,
2571 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302572 return gemPortID, nil
2573 }
2574 }
Shrey Baid26912972020-04-16 21:02:31 +05302575 return uint32(0), olterrors.NewErrNotFound("gem-port",
2576 log.Fields{
2577 "pktinkey": pktInkey,
2578 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002579
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002580}
2581
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002582func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2583 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002584 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002585 classifier[PacketTagType] = DoubleTag
2586 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002587 /* We manage flowId resource pool on per PON port basis.
2588 Since this situation is tricky, as a hack, we pass the NNI port
2589 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002590 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002591 on NNI port, use onu_id as -1 (invalid)
2592 ****************** CAVEAT *******************
2593 This logic works if the NNI Port Id falls within the same valid
2594 range of PON Port Ids. If this doesn't work for some OLT Vendor
2595 we need to have a re-look at this.
2596 *********************************************
2597 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002598 onuID := -1
2599 uniID := -1
2600 gemPortID := -1
2601 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002602 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302603 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302604 return olterrors.NewErrNotFound("nni-intreface-id",
2605 log.Fields{
2606 "classifier": classifier,
2607 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002608 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302609 }
2610
yasin saplid0566272021-12-21 09:10:30 +00002611 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, f.ponPortIdx, int32(onuID), logicalFlow.Id)
2612 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002613 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002614 return nil
yasin saplid0566272021-12-21 09:10:30 +00002615 } else if err != nil {
2616 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2617 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2618 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002620
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002621 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2622 log.Fields{
2623 "classifier": classifier,
2624 "action": action,
2625 "flowId": logicalFlow.Id,
2626 "intf-id": networkInterfaceID})
2627
David K. Bainbridge794735f2020-02-11 21:01:37 -08002628 classifierProto, err := makeOpenOltClassifierField(classifier)
2629 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002630 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002631 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002632 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002633 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002634 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002635 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002636 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002638 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2639 OnuId: int32(onuID), // OnuId not required
2640 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002641 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002642 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002643 AllocId: int32(allocID), // AllocId not used
2644 NetworkIntfId: int32(networkInterfaceID),
2645 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002646 Classifier: classifierProto,
2647 Action: actionProto,
2648 Priority: int32(logicalFlow.Priority),
2649 Cookie: logicalFlow.Cookie,
2650 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002651 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002652 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002654 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002655 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002656}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002657
Esin Karamanae41e2b2019-12-17 18:13:13 +00002658//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2659func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2660 var packetType string
2661 ovid, ivid := false, false
2662 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2663 vid := vlanID & VlanvIDMask
2664 if vid != ReservedVlan {
2665 ovid = true
2666 }
2667 }
2668 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2669 vid := uint32(metadata)
2670 if vid != ReservedVlan {
2671 ivid = true
2672 }
2673 }
2674 if ovid && ivid {
2675 packetType = DoubleTag
2676 } else if !ovid && !ivid {
2677 packetType = Untagged
2678 } else {
2679 packetType = SingleTag
2680 }
2681 return packetType
2682}
2683
2684//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002685func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002687 action := make(map[string]interface{})
2688 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2689 action[TrapToHost] = true
2690 /* We manage flowId resource pool on per PON port basis.
2691 Since this situation is tricky, as a hack, we pass the NNI port
2692 index (network_intf_id) as PON port Index for the flowId resource
2693 pool. Also, there is no ONU Id available for trapping packets
2694 on NNI port, use onu_id as -1 (invalid)
2695 ****************** CAVEAT *******************
2696 This logic works if the NNI Port Id falls within the same valid
2697 range of PON Port Ids. If this doesn't work for some OLT Vendor
2698 we need to have a re-look at this.
2699 *********************************************
2700 */
2701 onuID := -1
2702 uniID := -1
2703 gemPortID := -1
2704 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002705 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002706 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302707 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002708 "classifier": classifier,
2709 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002710 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002711 }
yasin saplid0566272021-12-21 09:10:30 +00002712
2713 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, f.ponPortIdx, int32(onuID), logicalFlow.Id)
2714 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002715 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002716 return nil
yasin saplid0566272021-12-21 09:10:30 +00002717 } else if err != nil {
2718 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2719 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2720 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002721 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002722
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723 classifierProto, err := makeOpenOltClassifierField(classifier)
2724 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002725 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002726 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002728 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002729 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002730 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002731 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002732 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002733 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2734 OnuId: int32(onuID), // OnuId not required
2735 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002736 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002737 FlowType: Downstream,
2738 AllocId: int32(allocID), // AllocId not used
2739 NetworkIntfId: int32(networkInterfaceID),
2740 GemportId: int32(gemPortID), // GemportId not used
2741 Classifier: classifierProto,
2742 Action: actionProto,
2743 Priority: int32(logicalFlow.Priority),
2744 Cookie: logicalFlow.Cookie,
2745 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002746 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002747 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002749 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002750
David K. Bainbridge794735f2020-02-11 21:01:37 -08002751 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002752}
2753
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2755 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302756 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002757 }
2758 if Dir == tp_pb.Direction_UPSTREAM {
2759 return "upstream", nil
2760 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2761 return "downstream", nil
2762 }
2763 return "", nil
2764}
2765
Kent Hagermane6ff1012020-07-14 15:07:53 -04002766// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302767func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002768 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002769 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002770 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002771 intfID := args[IntfID]
2772 onuID := args[OnuID]
2773 uniID := args[UniID]
2774 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002775 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002777 gemToAes := make(map[uint32]bool)
2778
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002779 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002780 var direction = tp_pb.Direction_UPSTREAM
2781 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002782 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002783 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002784 attributes = TpInst.UpstreamGemPortAttributeList
2785 } else {
2786 attributes = TpInst.DownstreamGemPortAttributeList
2787 direction = tp_pb.Direction_DOWNSTREAM
2788 }
2789 default:
2790 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002791 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002792 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002793
2794 if len(gemPorts) == 1 {
2795 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002796 gemPortID = gemPorts[0]
2797 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2799 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002800 pBitMap := attributes[idx].PbitMap
2801 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2802 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2803 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002804 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002805 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2806 if pbitSet == pbit1 {
2807 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2808 pbitToGem[pcp] = gemID
2809 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002810 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002811 }
2812 }
2813 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002814 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2815 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2816 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002817 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818 }
2819
Gamze Abaka7650be62021-02-26 10:50:36 +00002820 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2821 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2822
salmansiddiqui7ac62132019-08-22 03:58:50 +00002823 if ipProto, ok := classifierInfo[IPProto]; ok {
2824 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002825 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002826 "tp-id": tpID,
2827 "alloc-id": allocID,
2828 "intf-id": intfID,
2829 "onu-id": onuID,
2830 "uni-id": uniID,
2831 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002832 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002833 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002834 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002835 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})
2836 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002837 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002838 }
2839
Girish Gowdra32625212020-04-29 11:26:35 -07002840 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002841 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302842 log.Fields{
2843 "intf-id": intfID,
2844 "onu-id": onuID,
2845 "uni-id": uniID,
2846 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002849 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})
2850 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002851 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002852 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002853 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002854 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002855 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 }
2857 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002858 if ethType.(uint32) == EapEthType {
2859 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002860 "intf-id": intfID,
2861 "onu-id": onuID,
2862 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002863 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002864 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 var vlanID uint32
2866 if val, ok := classifierInfo[VlanVid]; ok {
2867 vlanID = (val.(uint32)) & VlanvIDMask
2868 } else {
2869 vlanID = DefaultMgmtVlan
2870 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002872 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002873 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})
2874 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002875 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002876 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002877 } else if ethType.(uint32) == PPPoEDEthType {
2878 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2879 "tp-id": tpID,
2880 "alloc-id": allocID,
2881 "intf-id": intfID,
2882 "onu-id": onuID,
2883 "uni-id": uniID,
2884 })
2885 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002887 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002888 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})
2889 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002890 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002891 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002893 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002895 "intf-id": intfID,
2896 "onu-id": onuID,
2897 "uni-id": uniID,
2898 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002899 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002900 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002902 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})
2903 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002904 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002906 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002907 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID,
2911 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002912 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002913 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002914 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
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 }
2919 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002920 return olterrors.NewErrInvalidValue(log.Fields{
2921 "intf-id": intfID,
2922 "onu-id": onuID,
2923 "uni-id": uniID,
2924 "classifier": classifierInfo,
2925 "action": actionInfo,
2926 "flow": flow},
2927 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
2929 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002930 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002931 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002932 logger.Warn(ctx, err)
2933 }
2934 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002935 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936}
2937
Gamze Abakacb0e6772021-06-10 08:32:12 +00002938func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002939 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2940 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2941 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 +05302942 for i := 0; i < len(tpInstances); i++ {
2943 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002944 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002945 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002946 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002947 log.Fields{
2948 "device-id": f.deviceHandler.device.Id,
2949 "intfID": sq.intfID,
2950 "onuID": sq.onuID,
2951 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002952 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002953 })
2954 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302955 }
2956 }
2957 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002958 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002959}
2960
Neha Sharma96b7bf22020-06-15 10:37:32 +00002961func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002962 for _, field := range flows.GetOfbFields(flow) {
2963 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002965 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002966 } else if field.Type == flows.ETH_DST {
2967 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002969 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002970 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002971 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002972 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002975 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05302976 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
2977 if field.GetVlanVid() != ReservedVlan {
2978 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
2979 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
2980 }
Scott Baker355d1742019-10-24 10:57:52 -07002981 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002983 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002984 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002985 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002986 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002987 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002988 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002989 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002990 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002993 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002994 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002996 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002997 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002999 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 return
3005 }
3006 }
3007}
3008
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003010 for _, action := range flows.GetActions(flow) {
3011 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003013 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003016 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003017 }
Scott Baker355d1742019-10-24 10:57:52 -07003018 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003020 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003021 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003022 if out := action.GetPush(); out != nil {
3023 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003025 } else {
3026 actionInfo[PushVlan] = true
3027 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303029 log.Fields{
3030 "push-tpid": actionInfo[TPID].(uint32),
3031 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 }
3033 }
Scott Baker355d1742019-10-24 10:57:52 -07003034 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 if out := action.GetSetField(); out != nil {
3036 if field := out.GetField(); field != nil {
3037 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003038 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3041 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 }
3043 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003044 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003047 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 }
3049 }
3050 return nil
3051}
3052
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003054 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003055 fieldtype := ofbField.GetType()
3056 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003057 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3058 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003060 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003062 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003063 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3064 pcp := ofbField.GetVlanPcp()
3065 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003066 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003067 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003069 }
3070 }
3071}
3072
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003074 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003076 } else {
3077 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003079 }
3080}
3081
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003083 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003086 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003087 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303090 log.Fields{
3091 "newinport": classifierInfo[InPort].(uint32),
3092 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303094 return olterrors.NewErrNotFound("child-in-port",
3095 log.Fields{
3096 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3097 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 }
3099 }
3100 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003103 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003104 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003105 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303107 log.Fields{
3108 "newoutport": actionInfo[Output].(uint32),
3109 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003110 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303111 return olterrors.NewErrNotFound("out-port",
3112 log.Fields{
3113 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3114 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 }
3116 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003117 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003118 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303121 log.Fields{
3122 "newinport": actionInfo[Output].(uint32),
3123 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303125 return olterrors.NewErrNotFound("nni-port",
3126 log.Fields{
3127 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3128 "in-port": classifierInfo[InPort].(uint32),
3129 "out-port": actionInfo[Output].(uint32),
3130 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003131 }
3132 }
3133 }
3134 return nil
3135}
Gamze Abakafee36392019-10-03 11:17:24 +00003136
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003138 /* Metadata 8 bytes:
3139 Most Significant 2 Bytes = Inner VLAN
3140 Next 2 Bytes = Tech Profile ID(TPID)
3141 Least Significant 4 Bytes = Port ID
3142 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3143 subscriber related flows.
3144 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003146 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003147 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003148 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003150 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003151}
3152
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003153func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003154 for _, sliceElement := range slice {
3155 if sliceElement == item {
3156 return slice
3157 }
3158 }
3159 return append(slice, item)
3160}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303161
3162// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303164
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003165 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303166 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003167 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003168 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003170 log.Fields{
3171 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003172 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003173 return uint32(0), err
3174 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303176 return intfID, nil
3177 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003178 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003179 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003181 log.Fields{
3182 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003183 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003184 return uint32(0), err
3185 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303187 return intfID, nil
3188 }
3189 return uint32(0), nil
3190}
3191
3192// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003193func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3194 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3195 if err != nil {
3196 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3197 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3198 return
3199 }
3200 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003201
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003202 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003203 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003204 f.packetInGemPortLock.RUnlock()
3205
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303206 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003207 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 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 +05303209 log.Fields{
3210 "pktinkey": pktInkey,
3211 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003212 return
3213 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303214 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003215 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003216 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003218
npujarec5762e2020-01-01 14:08:48 +05303219 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003220 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 +05303221 log.Fields{
3222 "pktinkey": pktInkey,
3223 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303224}
3225
Esin Karaman7fb80c22020-07-16 14:23:33 +00003226//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3227func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3228 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003229 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003230 return 0, 0, errors.New("invalid packet length")
3231 }
3232 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3233 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3234
3235 var index int8
3236 if outerEthType == 0x8100 {
3237 if innerEthType == 0x8100 {
3238 // q-in-q 802.1ad or 802.1q double tagged packet.
3239 // get the inner vlanId
3240 index = 18
3241 } else {
3242 index = 14
3243 }
3244 priority := (packet[index] >> 5) & 0x7
3245 //13 bits composes vlanId value
3246 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3247 return vlan, priority, nil
3248 }
3249 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3250 return 0, 0, nil
3251}
3252
Girish Gowdra9602eb42020-09-09 15:50:39 -07003253//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3254// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003255func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003256 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003257 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3258 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003259 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003260 "flow-id": flow.Id,
3261 "device-id": f.deviceHandler.device.Id})
3262 // Remove from device
3263 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3264 // DKB
3265 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3266 log.Fields{
3267 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003268 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003269 return err
3270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003271
3272 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003273}
3274
khenaidoodc2116e2021-10-19 17:33:19 -04003275func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003276 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003277 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003278 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003279 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003280 }
3281
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003282 switch tpInst := tpInst.(type) {
3283 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003284 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003285 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003286 DeviceId: onuDeviceID,
3287 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003288 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003289 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003290 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003291 case *tp_pb.EponTechProfileInstance:
3292 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003293 DeviceId: onuDeviceID,
3294 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003295 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003296 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003297 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003298 default:
3299 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003300 }
khenaidoodc2116e2021-10-19 17:33:19 -04003301 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003302 DeviceId: onuDeviceID,
3303 UniId: uniID,
3304 TpInstancePath: tpPath,
3305 TechTpInstance: nil,
3306 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003307}
3308
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003309// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3310func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3311
3312 intfID := sq.intfID
3313 onuID := sq.onuID
3314 uniID := sq.uniID
3315 tpID := sq.tpID
3316
3317 var reverseDirection string
3318 if sq.direction == tp_pb.Direction_UPSTREAM {
3319 reverseDirection = "downstream"
3320 } else {
3321 reverseDirection = "upstream"
3322 }
3323
3324 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3325 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3326 return
3327 }
3328
3329 // revert-delete tech-profile instance and delete tech profile id for onu
3330 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})
3331 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3332 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3333 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3334
3335 // free gem/alloc
3336 switch techprofileInst := sq.tpInst.(type) {
3337 case *tp_pb.TechProfileInstance:
3338 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3339 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3340 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08003341 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003342 }
3343}
3344
3345// revertSchduler is called when CreateQueues request fails
3346func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3347 // revert scheduler
3348 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})
3349 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3350 IntfId: sq.intfID, OnuId: sq.onuID,
3351 UniId: sq.uniID, PortNo: sq.uniPort,
3352 TrafficScheds: TrafficSched})
3353}
Girish Gowdra6071f382021-12-14 12:52:04 +05303354
3355// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3356func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
3357 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID)
3358 if err != nil {
3359 return olterrors.NewErrNotFound("meter",
3360 log.Fields{"intf-id": intfID,
3361 "onu-id": onuID,
3362 "uni-id": uniID,
3363 "device-id": f.deviceHandler.device.Id}, err)
3364 }
3365
3366 if meterInfo != nil {
3367 // If RefCnt become 0 clear the meter information from the DB.
3368 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
3369 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID); err != nil {
3370 return err
3371 }
3372 } else if meterInfo.MeterID != meterID {
3373 logger.Errorw(ctx, "meter-mismatch-for-direction",
3374 log.Fields{"direction": direction,
3375 "kv-store-meter-id": meterInfo.MeterID,
3376 "meter-id-in-flow": meterID,
3377 "device-id": f.deviceHandler.device.Id})
3378 return olterrors.NewErrInvalidValue(log.Fields{
3379 "unsupported": "meter-id",
3380 "kv-store-meter-id": meterInfo.MeterID,
3381 "meter-id-in-flow": meterID,
3382 "device-id": f.deviceHandler.device.Id}, nil)
3383 }
3384 }
3385 return nil
3386}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003387
3388func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3389 /* After we successfully remove the scheduler configuration on the OLT device,
3390 * delete the meter id on the KV store.
3391 */
3392 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
3393 if err != nil {
3394 return olterrors.NewErrAdapter("unable-to-remove-meter",
3395 log.Fields{
3396 "onu": sq.onuID,
3397 "device-id": f.deviceHandler.device.Id,
3398 "intf-id": sq.intfID,
3399 "onu-id": sq.onuID,
3400 "uni-id": sq.uniID,
3401 "uni-port": sq.uniPort}, err)
3402 }
3403 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3404 log.Fields{
3405 "dir": direction,
3406 "device-id": f.deviceHandler.device.Id,
3407 "intf-id": sq.intfID,
3408 "onu-id": sq.onuID,
3409 "uni-id": sq.uniID,
3410 "uni-port": sq.uniPort})
3411 return err
3412}