blob: 9b3a9def9bb72244236428f75cf99eb2e104c072 [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 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001918 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1919 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001920 log.Fields{
1921 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001922 "path": tpPath}, err).Log()
1923 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001924 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001925
1926 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001927 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001928 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001929 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1930 gemPortID := gemPort.GemportId
yasin sapli9e4c5092022-02-01 13:52:33 +00001931 used := f.resourceMgr.IsGemPortUsedByAnotherFlow(gemPortID, flowID)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001932 if used {
yasin sapli9e4c5092022-02-01 13:52:33 +00001933 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, intfID, gemPortID)
1934 if err != nil {
1935 return err
1936 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001937 for i, flowIDinMap := range flowIDs {
1938 if flowIDinMap == flowID {
1939 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001940 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1941 return err
1942 }
1943 break
1944 }
1945 }
1946 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1947 log.Fields{
1948 "gemport-id": gemPortID,
1949 "usedByFlows": flowIDs,
1950 "currentFlow": flowID,
1951 "device-id": f.deviceHandler.device.Id})
1952 allGemPortsFree = false
1953 }
1954 }
1955 if !allGemPortsFree {
1956 return nil
1957 }
1958 }
1959
1960 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 -08001961
1962 // 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 +00001963 switch techprofileInst := techprofileInst.(type) {
1964 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001965 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
1966 logger.Warn(ctx, err)
1967 }
1968 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1969 logger.Warn(ctx, err)
1970 }
1971
1972 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1973 gemPortID := gemPort.GemportId
Girish Gowdraf3728b12022-02-02 21:46:51 -08001974 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
1975
yasin sapli9e4c5092022-02-01 13:52:33 +00001976 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001977 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1978 log.Fields{
1979 "err": err,
1980 "intf": intfID,
1981 "onu-id": onuID,
1982 "uni-id": uniID,
1983 "device-id": f.deviceHandler.device.Id,
1984 "gemport-id": gemPortID})
1985 }
1986
1987 }
1988 // Remove queues at OLT in upstream and downstream direction
1989 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1990 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1991 logger.Warn(ctx, err)
1992 }
1993 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1994 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1995 logger.Warn(ctx, err)
1996 }
1997 }
1998
1999 switch techprofileInst := techprofileInst.(type) {
2000 case *tp_pb.TechProfileInstance:
2001 // 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 +01002002 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2003 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2004 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002005 // all alloc object references removed, remove upstream scheduler
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002006 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002007 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002008 logger.Warn(ctx, err)
2009 }
2010 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002011 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
2012 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
2013 } else {
2014 // just remove meter reference for the upstream direction for the current pon/onu/uni
2015 // 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
2016 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2017 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002018 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002019 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2020 // but still preserve it on the resource pool.
2021 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
2022 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002023
Girish Gowdraf3728b12022-02-02 21:46:51 -08002024 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2025 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2026 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
2027 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2028 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002029 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002030 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002031 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002032 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002033 logger.Warn(ctx, err)
2034 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002035 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002036 logger.Warn(ctx, err)
2037 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002038 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002039 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002040 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302041 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002042 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302043 "onu-id": onuID,
2044 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002045 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002046 "alloc-id": techprofileInst.AllocId,
2047 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002048 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002049 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002050 default:
2051 logger.Errorw(ctx, "error-unknown-tech",
2052 log.Fields{
2053 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002054 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002055
2056 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2057 switch techprofileInst := techprofileInst.(type) {
2058 case *tp_pb.TechProfileInstance:
2059 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2060 // Delete the gem port on the ONU.
2061 if sendDeleteGemRequest {
2062 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2063 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2064 log.Fields{
2065 "err": err,
2066 "intfID": intfID,
2067 "onu-id": onuID,
2068 "uni-id": uniID,
2069 "device-id": f.deviceHandler.device.Id,
2070 "gemport-id": gemPort.GemportId})
2071 }
2072 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId)
2073 }
2074 }
2075 }
2076
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302077 return nil
2078}
2079
David K. Bainbridge794735f2020-02-11 21:01:37 -08002080// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002081func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002082 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302083 log.Fields{
2084 "flowDirection": flowDirection,
2085 "flow": *flow,
2086 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002087
2088 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002089 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002090 }
2091
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302092 var ethType, ipProto, inPort uint32
2093 for _, field := range flows.GetOfbFields(flow) {
2094 if field.Type == flows.IP_PROTO {
2095 ipProto = field.GetIpProto()
2096 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2097 } else if field.Type == flows.ETH_TYPE {
2098 ethType = field.GetEthType()
2099 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2100 } else if field.Type == flows.IN_PORT {
2101 inPort = field.GetPort()
2102 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2103 }
2104 }
2105 portType := plt.IntfIDToPortTypeName(inPort)
2106 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2107 (portType == voltha.Port_ETHERNET_NNI) {
2108 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2109 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2110 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2111 // No more processing needed for trap from nni flows.
2112 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302113
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302114 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302115 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002116 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002117 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302118 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002119 onuID := int32(onu)
2120 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002121 tpID, err := getTpIDFromFlow(ctx, flow)
2122 if err != nil {
2123 return olterrors.NewErrNotFound("tp-id",
2124 log.Fields{
2125 "flow": flow,
2126 "intf-id": Intf,
2127 "onu-id": onuID,
2128 "uni-id": uniID,
2129 "device-id": f.deviceHandler.device.Id}, err)
2130 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302131
Neha Sharma96b7bf22020-06-15 10:37:32 +00002132 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302133 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002134 "flow-id": flow.Id,
2135 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302136 "onu-id": onuID,
2137 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302138
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002139 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2140 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002141 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2142 return err
2143 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002144
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002145 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002146 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2147 "flow-id": flow.Id,
2148 "device-id": f.deviceHandler.device.Id,
2149 "onu-id": onuID,
2150 "intf": Intf,
2151 "err": err,
2152 })
2153 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302154 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002155
Girish Gowdra82c80982021-03-26 16:22:02 -07002156 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2157 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2158 return err
2159 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002160 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002161}
2162
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002163//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002164func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002165
Matteo Scandolof16389e2021-05-18 00:47:08 +00002166 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302167 var direction string
2168 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002169
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302170 for _, action := range flows.GetActions(flow) {
2171 if action.Type == flows.OUTPUT {
2172 if out := action.GetOutput(); out != nil {
2173 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002174 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302175 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002176 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002177 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002178 }
2179 }
2180 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002181
2182 if flows.HasGroup(flow) {
2183 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002184 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002185 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302186 direction = Upstream
2187 } else {
2188 direction = Downstream
2189 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302190
Girish Gowdracefae192020-03-19 18:14:10 -07002191 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002192 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002193
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002194 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002195}
2196
Esin Karamanae41e2b2019-12-17 18:13:13 +00002197//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2198func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002199 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002200 if ethType, ok := classifierInfo[EthType]; ok {
2201 if ethType.(uint32) == IPv4EthType {
2202 if ipProto, ok := classifierInfo[IPProto]; ok {
2203 if ipProto.(uint32) == IgmpProto {
2204 return true
2205 }
2206 }
2207 }
2208 }
2209 }
2210 return false
2211}
2212
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002213// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002214func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002215 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2216 // The device itself is going to be reset as part of deletion. So nothing to be done.
2217 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2218 return nil
2219 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002220 // Step1 : Fill flowControlBlock
2221 // Step2 : Push the flowControlBlock to ONU channel
2222 // Step3 : Wait on response channel for response
2223 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002224 startTime := time.Now()
2225 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002226 errChan := make(chan error)
2227 flowCb := flowControlBlock{
2228 ctx: ctx,
2229 addFlow: addFlow,
2230 flow: flow,
2231 flowMetadata: flowMetadata,
2232 errChan: &errChan,
2233 }
2234 inPort, outPort := getPorts(flow)
2235 var onuID uint32
2236 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002237 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002238 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002239 if f.flowHandlerRoutineActive[onuID] {
2240 // inPort or outPort is InvalidPort for trap-from-nni flows.
2241 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2242 // Send the flowCb on the ONU flow channel
2243 f.incomingFlows[onuID] <- flowCb
2244 // Wait on the channel for flow handlers return value
2245 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002246 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002247 return err
2248 }
2249 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2250 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002251}
2252
2253// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2254// 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 -07002255func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002256 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002257 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002258 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002259 // block on the channel to receive an incoming flow
2260 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002261 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002262 if flowCb.addFlow {
2263 logger.Info(flowCb.ctx, "adding-flow-start")
2264 startTime := time.Now()
2265 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2266 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2267 // Pass the return value over the return channel
2268 *flowCb.errChan <- err
2269 } else {
2270 logger.Info(flowCb.ctx, "removing-flow-start")
2271 startTime := time.Now()
2272 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2273 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2274 // Pass the return value over the return channel
2275 *flowCb.errChan <- err
2276 }
2277 case <-stopHandler:
2278 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2279 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002280 }
2281 }
2282}
2283
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002284// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002285func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002286 for i, v := range f.stopFlowHandlerRoutine {
2287 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002288 select {
2289 case v <- true:
2290 case <-time.After(time.Second * 5):
2291 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2292 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002293 }
2294 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002295 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002296 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2297}
2298
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002299// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302300// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002301func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002302 classifierInfo := make(map[string]interface{})
2303 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002304 var UsMeterID uint32
2305 var DsMeterID uint32
2306
Neha Sharma96b7bf22020-06-15 10:37:32 +00002307 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302308 log.Fields{
2309 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002310 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002311 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002312
Neha Sharma96b7bf22020-06-15 10:37:32 +00002313 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002314 if err != nil {
2315 // Error logging is already done in the called function
2316 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002317 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302318 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002319
Esin Karamanccb714b2019-11-29 15:02:06 +00002320 if flows.HasGroup(flow) {
2321 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002322 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002323 }
2324
manikkaraj k17652a72019-05-06 09:06:36 -04002325 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002326 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002327 if err != nil {
2328 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002329 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002330 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002331
Neha Sharma96b7bf22020-06-15 10:37:32 +00002332 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302333 log.Fields{
2334 "classifierinfo_inport": classifierInfo[InPort],
2335 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002336 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002337
Humera Kouser94d7a842019-08-25 19:04:32 -04002338 if ethType, ok := classifierInfo[EthType]; ok {
2339 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002340 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002341 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002342 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002343 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002344 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002345 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2346 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2347 }
2348 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002349 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002350 if ipProto, ok := classifierInfo[IPProto]; ok {
2351 if ipProto.(uint32) == IPProtoDhcp {
2352 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302353 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002355 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002356 }
2357 }
2358 }
2359 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002360 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002361 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002362 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002363 }
A R Karthick1f85b802019-10-11 05:06:05 +00002364
npujarec5762e2020-01-01 14:08:48 +05302365 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002366
Girish Gowdra6071f382021-12-14 12:52:04 +05302367 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002368 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302369 return olterrors.NewErrNotFound("tpid-for-flow",
2370 log.Fields{
2371 "flow": flow,
2372 "intf-id": IntfID,
2373 "onu-id": onuID,
2374 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002375 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302377 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302378 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302379 "intf-id": intfID,
2380 "onu-id": onuID,
2381 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002382 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002383 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302385 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2386 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2387 return err
2388 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002389 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002390 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002391 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302392 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2393 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2394 return err
2395 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002396 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302397 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002398}
Girish Gowdra3d633032019-12-10 16:37:05 +05302399
Esin Karamanccb714b2019-11-29 15:02:06 +00002400// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002401func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302402 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302404 "classifier-info": classifierInfo,
2405 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002406
Esin Karaman65409d82020-03-18 10:58:18 +00002407 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002408 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002409 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002410 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002411
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002412 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002413
David K. Bainbridge794735f2020-02-11 21:01:37 -08002414 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002415
yasin saplid0566272021-12-21 09:10:30 +00002416 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), flow.Id)
2417 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002419 return nil
yasin saplid0566272021-12-21 09:10:30 +00002420 } else if err != nil {
2421 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2422 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2423 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002424 }
yasin saplid0566272021-12-21 09:10:30 +00002425
David K. Bainbridge794735f2020-02-11 21:01:37 -08002426 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2427 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002428 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002429 }
2430 groupID := actionInfo[GroupID].(uint32)
2431 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002432 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002433 FlowType: Multicast,
2434 NetworkIntfId: int32(networkInterfaceID),
2435 GroupId: groupID,
2436 Classifier: classifierProto,
2437 Priority: int32(flow.Priority),
2438 Cookie: flow.Cookie}
2439
Kent Hagermane6ff1012020-07-14 15:07:53 -04002440 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002441 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002442 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002443 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002444 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002445 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002446 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002447 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002448 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002449 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002450 //cached group can be removed now
2451 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002452 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002453 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002454 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002455
David K. Bainbridge794735f2020-02-11 21:01:37 -08002456 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002457}
2458
Esin Karaman65409d82020-03-18 10:58:18 +00002459//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2460func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2461 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002462 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002463 if err != nil {
2464 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2465 }
2466 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002467 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002468
2469 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2470 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002471}
2472
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002473//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002474func (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 -07002475
Neha Sharma96b7bf22020-06-15 10:37:32 +00002476 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302477 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002478 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302479 log.Fields{
2480 "intf-id": intfID,
2481 "onu-id": onuID,
2482 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002483 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302484 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002485 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002486
Neha Sharma96b7bf22020-06-15 10:37:32 +00002487 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002488 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002489 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002490 UniId: uniID,
2491 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002492 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002493 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002494 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002495
2496 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2497 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302498 return olterrors.NewErrCommunication("send-techprofile-download-request",
2499 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002500 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302501 "to-adapter": onuDev.deviceType,
2502 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002503 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002504 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002505 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302506 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302507}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002508
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002509//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302510func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002511 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002512
2513 if packetIn.IntfType == "pon" {
2514 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002515 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002516 onuID, uniID := packetIn.OnuId, packetIn.UniId
2517 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 +00002518
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002519 if packetIn.PortNo != 0 {
2520 logicalPortNum = packetIn.PortNo
2521 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002522 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002523 }
2524 // 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 +00002525 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002526 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002527 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002528 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002529
2530 if logger.V(log.DebugLevel) {
2531 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2532 log.Fields{
2533 "logical-port-num": logicalPortNum,
2534 "intf-type": packetIn.IntfType,
2535 "packet": hex.EncodeToString(packetIn.Pkt),
2536 })
2537 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002538 return logicalPortNum, nil
2539}
2540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002541//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002542func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002543 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002544
2545 ctag, priority, err := getCTagFromPacket(ctx, packet)
2546 if err != nil {
2547 return 0, err
2548 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302549
Esin Karaman7fb80c22020-07-16 14:23:33 +00002550 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002551 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002552 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002553 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002554 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302555 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002556 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302557 log.Fields{
2558 "pktinkey": pktInkey,
2559 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002560
2561 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002562 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302563 //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 +00002564 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302565 if err == nil {
2566 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002567 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302568 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002569 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002570 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302571 log.Fields{
2572 "pktinkey": pktInkey,
2573 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302574 return gemPortID, nil
2575 }
2576 }
Shrey Baid26912972020-04-16 21:02:31 +05302577 return uint32(0), olterrors.NewErrNotFound("gem-port",
2578 log.Fields{
2579 "pktinkey": pktInkey,
2580 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002581
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002582}
2583
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002584func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2585 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002586 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002587 classifier[PacketTagType] = DoubleTag
2588 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002589 /* We manage flowId resource pool on per PON port basis.
2590 Since this situation is tricky, as a hack, we pass the NNI port
2591 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002592 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593 on NNI port, use onu_id as -1 (invalid)
2594 ****************** CAVEAT *******************
2595 This logic works if the NNI Port Id falls within the same valid
2596 range of PON Port Ids. If this doesn't work for some OLT Vendor
2597 we need to have a re-look at this.
2598 *********************************************
2599 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002600 onuID := -1
2601 uniID := -1
2602 gemPortID := -1
2603 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002604 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302605 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302606 return olterrors.NewErrNotFound("nni-intreface-id",
2607 log.Fields{
2608 "classifier": classifier,
2609 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002610 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302611 }
2612
yasin saplid0566272021-12-21 09:10:30 +00002613 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, f.ponPortIdx, int32(onuID), logicalFlow.Id)
2614 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002615 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002616 return nil
yasin saplid0566272021-12-21 09:10:30 +00002617 } else if err != nil {
2618 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2619 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2620 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002621 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002622
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002623 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2624 log.Fields{
2625 "classifier": classifier,
2626 "action": action,
2627 "flowId": logicalFlow.Id,
2628 "intf-id": networkInterfaceID})
2629
David K. Bainbridge794735f2020-02-11 21:01:37 -08002630 classifierProto, err := makeOpenOltClassifierField(classifier)
2631 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002632 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002633 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002634 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002635 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002636 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002637 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002638 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002639 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002640 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2641 OnuId: int32(onuID), // OnuId not required
2642 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002643 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002644 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002645 AllocId: int32(allocID), // AllocId not used
2646 NetworkIntfId: int32(networkInterfaceID),
2647 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002648 Classifier: classifierProto,
2649 Action: actionProto,
2650 Priority: int32(logicalFlow.Priority),
2651 Cookie: logicalFlow.Cookie,
2652 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002653 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002654 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002655 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002656 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002657 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002658}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002659
Esin Karamanae41e2b2019-12-17 18:13:13 +00002660//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2661func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2662 var packetType string
2663 ovid, ivid := false, false
2664 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2665 vid := vlanID & VlanvIDMask
2666 if vid != ReservedVlan {
2667 ovid = true
2668 }
2669 }
2670 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2671 vid := uint32(metadata)
2672 if vid != ReservedVlan {
2673 ivid = true
2674 }
2675 }
2676 if ovid && ivid {
2677 packetType = DoubleTag
2678 } else if !ovid && !ivid {
2679 packetType = Untagged
2680 } else {
2681 packetType = SingleTag
2682 }
2683 return packetType
2684}
2685
2686//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002687func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002688 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002689 action := make(map[string]interface{})
2690 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2691 action[TrapToHost] = true
2692 /* We manage flowId resource pool on per PON port basis.
2693 Since this situation is tricky, as a hack, we pass the NNI port
2694 index (network_intf_id) as PON port Index for the flowId resource
2695 pool. Also, there is no ONU Id available for trapping packets
2696 on NNI port, use onu_id as -1 (invalid)
2697 ****************** CAVEAT *******************
2698 This logic works if the NNI Port Id falls within the same valid
2699 range of PON Port Ids. If this doesn't work for some OLT Vendor
2700 we need to have a re-look at this.
2701 *********************************************
2702 */
2703 onuID := -1
2704 uniID := -1
2705 gemPortID := -1
2706 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002707 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002708 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302709 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002710 "classifier": classifier,
2711 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002712 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002713 }
yasin saplid0566272021-12-21 09:10:30 +00002714
2715 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, f.ponPortIdx, int32(onuID), logicalFlow.Id)
2716 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002717 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002718 return nil
yasin saplid0566272021-12-21 09:10:30 +00002719 } else if err != nil {
2720 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2721 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2722 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002723 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002724
David K. Bainbridge794735f2020-02-11 21:01:37 -08002725 classifierProto, err := makeOpenOltClassifierField(classifier)
2726 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002727 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002728 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002729 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002730 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002731 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002732 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002734 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002735 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2736 OnuId: int32(onuID), // OnuId not required
2737 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002738 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002739 FlowType: Downstream,
2740 AllocId: int32(allocID), // AllocId not used
2741 NetworkIntfId: int32(networkInterfaceID),
2742 GemportId: int32(gemPortID), // GemportId not used
2743 Classifier: classifierProto,
2744 Action: actionProto,
2745 Priority: int32(logicalFlow.Priority),
2746 Cookie: logicalFlow.Cookie,
2747 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002748 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002749 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002750 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002752
David K. Bainbridge794735f2020-02-11 21:01:37 -08002753 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002754}
2755
salmansiddiqui7ac62132019-08-22 03:58:50 +00002756func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2757 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302758 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002759 }
2760 if Dir == tp_pb.Direction_UPSTREAM {
2761 return "upstream", nil
2762 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2763 return "downstream", nil
2764 }
2765 return "", nil
2766}
2767
Kent Hagermane6ff1012020-07-14 15:07:53 -04002768// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302769func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002770 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002771 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002772 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002773 intfID := args[IntfID]
2774 onuID := args[OnuID]
2775 uniID := args[UniID]
2776 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002777 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002778 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002779 gemToAes := make(map[uint32]bool)
2780
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002781 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002782 var direction = tp_pb.Direction_UPSTREAM
2783 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002784 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002785 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002786 attributes = TpInst.UpstreamGemPortAttributeList
2787 } else {
2788 attributes = TpInst.DownstreamGemPortAttributeList
2789 direction = tp_pb.Direction_DOWNSTREAM
2790 }
2791 default:
2792 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002793 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002794 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002795
2796 if len(gemPorts) == 1 {
2797 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002798 gemPortID = gemPorts[0]
2799 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002800 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2801 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002802 pBitMap := attributes[idx].PbitMap
2803 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2804 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2805 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002806 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002807 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2808 if pbitSet == pbit1 {
2809 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2810 pbitToGem[pcp] = gemID
2811 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002812 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002813 }
2814 }
2815 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002816 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2817 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2818 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002819 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002820 }
2821
Gamze Abaka7650be62021-02-26 10:50:36 +00002822 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2823 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2824
salmansiddiqui7ac62132019-08-22 03:58:50 +00002825 if ipProto, ok := classifierInfo[IPProto]; ok {
2826 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002827 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002828 "tp-id": tpID,
2829 "alloc-id": allocID,
2830 "intf-id": intfID,
2831 "onu-id": onuID,
2832 "uni-id": uniID,
2833 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002834 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002835 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002836 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002837 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})
2838 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002839 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002840 }
2841
Girish Gowdra32625212020-04-29 11:26:35 -07002842 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002843 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302844 log.Fields{
2845 "intf-id": intfID,
2846 "onu-id": onuID,
2847 "uni-id": uniID,
2848 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002849 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002850 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002851 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})
2852 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002853 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002854 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002855 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002856 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002857 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002858 }
2859 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002860 if ethType.(uint32) == EapEthType {
2861 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002862 "intf-id": intfID,
2863 "onu-id": onuID,
2864 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002865 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002866 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002867 var vlanID uint32
2868 if val, ok := classifierInfo[VlanVid]; ok {
2869 vlanID = (val.(uint32)) & VlanvIDMask
2870 } else {
2871 vlanID = DefaultMgmtVlan
2872 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002873 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002874 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002875 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})
2876 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002877 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002878 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002879 } else if ethType.(uint32) == PPPoEDEthType {
2880 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2881 "tp-id": tpID,
2882 "alloc-id": allocID,
2883 "intf-id": intfID,
2884 "onu-id": onuID,
2885 "uni-id": uniID,
2886 })
2887 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002888 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002889 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002890 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2891 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002892 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002893 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002894 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002896 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002897 "intf-id": intfID,
2898 "onu-id": onuID,
2899 "uni-id": uniID,
2900 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002903 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002904 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2905 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002906 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002907 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002908 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002909 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002910 "intf-id": intfID,
2911 "onu-id": onuID,
2912 "uni-id": uniID,
2913 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002914 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002915 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002916 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002917 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})
2918 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002919 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002920 }
2921 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002922 return olterrors.NewErrInvalidValue(log.Fields{
2923 "intf-id": intfID,
2924 "onu-id": onuID,
2925 "uni-id": uniID,
2926 "classifier": classifierInfo,
2927 "action": actionInfo,
2928 "flow": flow},
2929 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002930 }
2931 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002932 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002933 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002934 logger.Warn(ctx, err)
2935 }
2936 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002937 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938}
2939
Gamze Abakacb0e6772021-06-10 08:32:12 +00002940func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002941 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2942 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2943 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 +05302944 for i := 0; i < len(tpInstances); i++ {
2945 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002946 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002947 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002948 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002949 log.Fields{
2950 "device-id": f.deviceHandler.device.Id,
2951 "intfID": sq.intfID,
2952 "onuID": sq.onuID,
2953 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002954 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002955 })
2956 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302957 }
2958 }
2959 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002960 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002961}
2962
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002964 for _, field := range flows.GetOfbFields(flow) {
2965 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002966 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002967 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002968 } else if field.Type == flows.ETH_DST {
2969 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002970 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002971 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002973 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002974 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002975 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002976 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002977 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05302978 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
2979 if field.GetVlanVid() != ReservedVlan {
2980 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
2981 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
2982 }
Scott Baker355d1742019-10-24 10:57:52 -07002983 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002984 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002985 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002986 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002987 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002988 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002989 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002990 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002991 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002992 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002995 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002996 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002997 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002998 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002999 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003000 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003001 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003005 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 return
3007 }
3008 }
3009}
3010
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003012 for _, action := range flows.GetActions(flow) {
3013 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003014 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003015 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003016 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003017 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003018 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 }
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 if out := action.GetPush(); out != nil {
3025 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 } else {
3028 actionInfo[PushVlan] = true
3029 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003030 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303031 log.Fields{
3032 "push-tpid": actionInfo[TPID].(uint32),
3033 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003034 }
3035 }
Scott Baker355d1742019-10-24 10:57:52 -07003036 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 if out := action.GetSetField(); out != nil {
3038 if field := out.GetField(); field != nil {
3039 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003040 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3043 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003044 }
3045 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003046 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003047 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003049 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003050 }
3051 }
3052 return nil
3053}
3054
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003056 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003057 fieldtype := ofbField.GetType()
3058 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003059 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3060 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003062 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003064 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003065 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3066 pcp := ofbField.GetVlanPcp()
3067 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003068 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003069 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003071 }
3072 }
3073}
3074
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003076 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003077 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003078 } else {
3079 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003081 }
3082}
3083
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003085 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003086 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003088 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003089 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303092 log.Fields{
3093 "newinport": classifierInfo[InPort].(uint32),
3094 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303096 return olterrors.NewErrNotFound("child-in-port",
3097 log.Fields{
3098 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3099 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003100 }
3101 }
3102 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003105 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003106 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003107 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303109 log.Fields{
3110 "newoutport": actionInfo[Output].(uint32),
3111 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303113 return olterrors.NewErrNotFound("out-port",
3114 log.Fields{
3115 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3116 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 }
3118 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003119 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003120 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003122 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303123 log.Fields{
3124 "newinport": actionInfo[Output].(uint32),
3125 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303127 return olterrors.NewErrNotFound("nni-port",
3128 log.Fields{
3129 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3130 "in-port": classifierInfo[InPort].(uint32),
3131 "out-port": actionInfo[Output].(uint32),
3132 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003133 }
3134 }
3135 }
3136 return nil
3137}
Gamze Abakafee36392019-10-03 11:17:24 +00003138
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003140 /* Metadata 8 bytes:
3141 Most Significant 2 Bytes = Inner VLAN
3142 Next 2 Bytes = Tech Profile ID(TPID)
3143 Least Significant 4 Bytes = Port ID
3144 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3145 subscriber related flows.
3146 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003147 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003148 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003149 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003152 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003153}
3154
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003155func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003156 for _, sliceElement := range slice {
3157 if sliceElement == item {
3158 return slice
3159 }
3160 }
3161 return append(slice, item)
3162}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303163
3164// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003165func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303166
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003167 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303168 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003169 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003170 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003172 log.Fields{
3173 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003174 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003175 return uint32(0), err
3176 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003177 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303178 return intfID, nil
3179 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003180 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003181 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003182 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003183 log.Fields{
3184 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003185 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003186 return uint32(0), err
3187 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003188 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303189 return intfID, nil
3190 }
3191 return uint32(0), nil
3192}
3193
3194// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003195func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3196 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3197 if err != nil {
3198 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3199 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3200 return
3201 }
3202 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003203
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003204 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003205 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003206 f.packetInGemPortLock.RUnlock()
3207
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303208 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003209 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003210 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 +05303211 log.Fields{
3212 "pktinkey": pktInkey,
3213 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003214 return
3215 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303216 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003218 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003219 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003220
npujarec5762e2020-01-01 14:08:48 +05303221 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 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 +05303223 log.Fields{
3224 "pktinkey": pktInkey,
3225 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303226}
3227
Esin Karaman7fb80c22020-07-16 14:23:33 +00003228//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3229func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3230 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003231 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003232 return 0, 0, errors.New("invalid packet length")
3233 }
3234 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3235 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3236
3237 var index int8
3238 if outerEthType == 0x8100 {
3239 if innerEthType == 0x8100 {
3240 // q-in-q 802.1ad or 802.1q double tagged packet.
3241 // get the inner vlanId
3242 index = 18
3243 } else {
3244 index = 14
3245 }
3246 priority := (packet[index] >> 5) & 0x7
3247 //13 bits composes vlanId value
3248 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3249 return vlan, priority, nil
3250 }
3251 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3252 return 0, 0, nil
3253}
3254
Girish Gowdra9602eb42020-09-09 15:50:39 -07003255//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3256// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003257func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003258 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003259 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3260 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003261 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003262 "flow-id": flow.Id,
3263 "device-id": f.deviceHandler.device.Id})
3264 // Remove from device
3265 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3266 // DKB
3267 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3268 log.Fields{
3269 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003270 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003271 return err
3272 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003273
3274 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003275}
3276
khenaidoodc2116e2021-10-19 17:33:19 -04003277func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003278 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003279 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003280 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003281 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003282 }
3283
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003284 switch tpInst := tpInst.(type) {
3285 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003286 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003287 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003288 DeviceId: onuDeviceID,
3289 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003290 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003291 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003292 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003293 case *tp_pb.EponTechProfileInstance:
3294 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003295 DeviceId: onuDeviceID,
3296 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003297 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003298 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003299 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003300 default:
3301 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003302 }
khenaidoodc2116e2021-10-19 17:33:19 -04003303 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003304 DeviceId: onuDeviceID,
3305 UniId: uniID,
3306 TpInstancePath: tpPath,
3307 TechTpInstance: nil,
3308 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003309}
3310
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003311// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3312func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3313
3314 intfID := sq.intfID
3315 onuID := sq.onuID
3316 uniID := sq.uniID
3317 tpID := sq.tpID
3318
3319 var reverseDirection string
3320 if sq.direction == tp_pb.Direction_UPSTREAM {
3321 reverseDirection = "downstream"
3322 } else {
3323 reverseDirection = "upstream"
3324 }
3325
3326 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3327 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3328 return
3329 }
3330
3331 // revert-delete tech-profile instance and delete tech profile id for onu
3332 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})
3333 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3334 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3335 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3336
3337 // free gem/alloc
3338 switch techprofileInst := sq.tpInst.(type) {
3339 case *tp_pb.TechProfileInstance:
3340 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3341 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3342 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08003343 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003344 }
3345}
3346
3347// revertSchduler is called when CreateQueues request fails
3348func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3349 // revert scheduler
3350 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})
3351 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3352 IntfId: sq.intfID, OnuId: sq.onuID,
3353 UniId: sq.uniID, PortNo: sq.uniPort,
3354 TrafficScheds: TrafficSched})
3355}
Girish Gowdra6071f382021-12-14 12:52:04 +05303356
3357// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3358func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
3359 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID)
3360 if err != nil {
3361 return olterrors.NewErrNotFound("meter",
3362 log.Fields{"intf-id": intfID,
3363 "onu-id": onuID,
3364 "uni-id": uniID,
3365 "device-id": f.deviceHandler.device.Id}, err)
3366 }
3367
3368 if meterInfo != nil {
3369 // If RefCnt become 0 clear the meter information from the DB.
3370 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
3371 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID); err != nil {
3372 return err
3373 }
3374 } else if meterInfo.MeterID != meterID {
3375 logger.Errorw(ctx, "meter-mismatch-for-direction",
3376 log.Fields{"direction": direction,
3377 "kv-store-meter-id": meterInfo.MeterID,
3378 "meter-id-in-flow": meterID,
3379 "device-id": f.deviceHandler.device.Id})
3380 return olterrors.NewErrInvalidValue(log.Fields{
3381 "unsupported": "meter-id",
3382 "kv-store-meter-id": meterInfo.MeterID,
3383 "meter-id-in-flow": meterID,
3384 "device-id": f.deviceHandler.device.Id}, nil)
3385 }
3386 }
3387 return nil
3388}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003389
3390func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3391 /* After we successfully remove the scheduler configuration on the OLT device,
3392 * delete the meter id on the KV store.
3393 */
3394 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
3395 if err != nil {
3396 return olterrors.NewErrAdapter("unable-to-remove-meter",
3397 log.Fields{
3398 "onu": sq.onuID,
3399 "device-id": f.deviceHandler.device.Id,
3400 "intf-id": sq.intfID,
3401 "onu-id": sq.onuID,
3402 "uni-id": sq.uniID,
3403 "uni-port": sq.uniPort}, err)
3404 }
3405 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3406 log.Fields{
3407 "dir": direction,
3408 "device-id": f.deviceHandler.device.Id,
3409 "intf-id": sq.intfID,
3410 "onu-id": sq.onuID,
3411 "uni-id": sq.uniID,
3412 "uni-port": sq.uniPort})
3413 return err
3414}