blob: 8b24630df692e71706a70bdbee68fd62fbb46a63 [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 {
yasin saplibddc2d72022-02-08 13:10:17 +0000260 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000261 }
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 saplibddc2d72022-02-08 13:10:17 +0000264 return f.resourceMgr.RegisterFlowIDForGem(ctx, 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 saplibddc2d72022-02-08 13:10:17 +0000268 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, 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 */
yasin saplibddc2d72022-02-08 13:10:17 +0000393 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, 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})
yasin saplibddc2d72022-02-08 13:10:17 +0000406 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800407 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 */
yasin saplibddc2d72022-02-08 13:10:17 +0000481 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, 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
yasin saplibddc2d72022-02-08 13:10:17 +0000588 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, 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))
yasin saplibddc2d72022-02-08 13:10:17 +0000687 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800688 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
yasin saplibddc2d72022-02-08 13:10:17 +0000802 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
803 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
804 tpPath := f.getTPpath(ctx, 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 }
yasin saplibddc2d72022-02-08 13:10:17 +0000830 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, 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 */
yasin saplibddc2d72022-02-08 13:10:17 +0000942 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, 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 }
yasin saplibddc2d72022-02-08 13:10:17 +0000945 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, 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 saplibddc2d72022-02-08 13:10:17 +0000951 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000952 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 saplibddc2d72022-02-08 13:10:17 +00001058 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001059 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301061 log.Fields{
1062 "device-id": f.deviceHandler.device.Id,
1063 "intf-id": intfID,
1064 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 return nil
yasin saplid0566272021-12-21 09:10:30 +00001066 } else if err != nil {
1067 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1068 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1069 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301070 }
yasin saplid0566272021-12-21 09:10:30 +00001071
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 classifierProto, err := makeOpenOltClassifierField(classifier)
1073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "classifier": *classifierProto,
1079 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001080 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "action": *actionProto,
1087 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 log.Fields{
1092 "classifier": classifier,
1093 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301094 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301096 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001099 OnuId: int32(onuID),
1100 UniId: int32(uniID),
1101 FlowId: logicalFlow.Id,
1102 FlowType: direction,
1103 AllocId: int32(allocID),
1104 NetworkIntfId: int32(networkIntfID),
1105 GemportId: int32(gemPortID),
1106 Classifier: classifierProto,
1107 Action: actionProto,
1108 Priority: int32(logicalFlow.Priority),
1109 Cookie: logicalFlow.Cookie,
1110 PortNo: flowContext.portNo,
1111 TechProfileId: tpID,
1112 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1113 PbitToGemport: flowContext.pbitToGem,
1114 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001115 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301120 log.Fields{"direction": direction,
1121 "device-id": f.deviceHandler.device.Id,
1122 "flow": flow,
1123 "intf-id": intfID,
1124 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301127}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128
Gamze Abaka7650be62021-02-26 10:50:36 +00001129func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1130
1131 intfID := flowContext.intfID
1132 onuID := flowContext.onuID
1133 uniID := flowContext.uniID
1134 logicalFlow := flowContext.logicalFlow
1135 classifier := flowContext.classifier
1136 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301139 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301142 "action": action,
1143 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
1147 // Clear the action map
1148 for k := range action {
1149 delete(action, k)
1150 }
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 action[TrapToHost] = true
1153 classifier[UDPSrc] = uint32(68)
1154 classifier[UDPDst] = uint32(67)
1155 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
yasin saplibddc2d72022-02-08 13:10:17 +00001157 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001158 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301160 log.Fields{
1161 "device-id": f.deviceHandler.device.Id,
1162 "intf-id": intfID,
1163 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 return nil
yasin saplid0566272021-12-21 09:10:30 +00001165 } else if err != nil {
1166 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1167 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1168 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301169 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "ul_classifier": classifier,
1174 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "intf-id": intfID,
1177 "onu-id": onuID,
1178 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 classifierProto, err := makeOpenOltClassifierField(classifier)
1181 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301182 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001185 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301187 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 }
1189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 OnuId: int32(onuID),
1192 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001194 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001195 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001197 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198 Classifier: classifierProto,
1199 Action: actionProto,
1200 Priority: int32(logicalFlow.Priority),
1201 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 PortNo: flowContext.portNo,
1203 TechProfileId: flowContext.tpID,
1204 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1205 PbitToGemport: flowContext.pbitToGem,
1206 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001207 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001214 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301215 "intf-id": intfID,
1216 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301217
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301219}
1220
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001222func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1223 delete(flowContext.classifier, VlanVid)
1224 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225}
1226
1227//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001228func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1229
1230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
yasin saplibddc2d72022-02-08 13:10:17 +00001255 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001256 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
yasin saplid0566272021-12-21 09:10:30 +00001259 } else if err != nil {
1260 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1261 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1262 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "ul_classifier": classifier,
1268 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301270 "device-id": f.deviceHandler.device.Id,
1271 "intf-id": intfID,
1272 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 classifierProto, err := makeOpenOltClassifierField(classifier)
1275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "classifier": *classifierProto,
1281 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001282 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301284 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 }
1286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 OnuId: int32(onuID),
1289 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001292 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 Classifier: classifierProto,
1296 Action: actionProto,
1297 Priority: int32(logicalFlow.Priority),
1298 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 PortNo: flowContext.portNo,
1300 TechProfileId: flowContext.tpID,
1301 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1302 PbitToGemport: flowContext.pbitToGem,
1303 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001340 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001346 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001347 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301349 "device-id": f.deviceHandler.device.Id,
1350 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 "intf-id": intfID,
1352 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
yasin saplid0566272021-12-21 09:10:30 +00001354 } else if err != nil {
1355 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1356 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1357 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301358 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001359 //Add Uplink EthType Flow
1360 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "ul_classifier": uplinkClassifier,
1363 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "intf-id": intfID,
1367 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1370 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301371 return olterrors.NewErrInvalidValue(log.Fields{
1372 "classifier": uplinkClassifier,
1373 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "classifier": *classifierProto,
1378 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001379 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301381 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "action": *actionProto,
1386 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301391 "action": action,
1392 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 }
1395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 OnuId: int32(onuID),
1398 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001399 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 AllocId: int32(allocID),
1402 NetworkIntfId: int32(networkIntfID),
1403 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 Classifier: classifierProto,
1405 Action: actionProto,
1406 Priority: int32(logicalFlow.Priority),
1407 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001409 TechProfileId: flowContext.tpID,
1410 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1411 PbitToGemport: flowContext.pbitToGem,
1412 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301418 log.Fields{
1419 "device-id": f.deviceHandler.device.Id,
1420 "onu-id": onuID,
1421 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001422 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301423 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
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
yasin saplibddc2d72022-02-08 13:10:17 +00001519func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, 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 {
yasin saplibddc2d72022-02-08 13:10:17 +00001534 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, 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))
yasin saplibddc2d72022-02-08 13:10:17 +00001542 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001543 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 saplibddc2d72022-02-08 13:10:17 +00001690 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001691 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001692 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001693 return nil
yasin saplid0566272021-12-21 09:10:30 +00001694 } else if err != nil {
1695 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1696 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1697 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001698 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001699
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1701 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301702 return olterrors.NewErrInvalidValue(
1703 log.Fields{
1704 "classifier": classifierInfo,
1705 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001706 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001707 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301708 log.Fields{
1709 "classifier": *classifierProto,
1710 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001711 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001712 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301713 return olterrors.NewErrInvalidValue(
1714 log.Fields{
1715 "action": actionInfo,
1716 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001717 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001718 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301719 log.Fields{
1720 "action": *actionProto,
1721 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001722
1723 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1724 OnuId: int32(onuID), // OnuId not required
1725 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001726 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001727 FlowType: Downstream,
1728 NetworkIntfId: int32(networkInterfaceID),
1729 GemportId: int32(gemPortID),
1730 Classifier: classifierProto,
1731 Action: actionProto,
1732 Priority: int32(flow.Priority),
1733 Cookie: flow.Cookie,
1734 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001735 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001736 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301737 log.Fields{
1738 "flow": downstreamflow,
1739 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001740 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001741 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301742 log.Fields{
1743 "device-id": f.deviceHandler.device.Id,
1744 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001745 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001746
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301748}
1749
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001750func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1751 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001752}
1753
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001754//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001755func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001756 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1757 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1758 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001759 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301760 log.Fields{
1761 "intf-id": intfID,
1762 "onu-id": onuID,
1763 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001764 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001765 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301766 return nil, olterrors.NewErrNotFound("onu-child-device",
1767 log.Fields{
1768 "onu-id": onuID,
1769 "intf-id": intfID,
1770 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771 }
khenaidoo106c61a2021-08-11 18:05:46 -04001772 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 -07001773 //better to ad the device to cache here.
1774 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1775 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781 }
1782
1783 return onuDev.(*OnuDevice), nil
1784}
1785
1786//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001787func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1788 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301789 log.Fields{
1790 "pon-port": intfID,
1791 "onu-id": onuID,
1792 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001793 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001794 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001795 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301796 return nil, olterrors.NewErrNotFound("onu",
1797 log.Fields{
1798 "interface-id": parentPortNo,
1799 "onu-id": onuID,
1800 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001801 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301802 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "device-id": f.deviceHandler.device.Id,
1806 "child_device_id": onuDevice.Id,
1807 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301808 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301809}
1810
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1812 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301813 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301815 log.Fields{
1816 "intf-id": intfID,
1817 "onu-id": onuID,
1818 "uni-id": uniID,
1819 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001820 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301821 }
1822
khenaidoodc2116e2021-10-19 17:33:19 -04001823 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001824 DeviceId: onuDev.deviceID,
1825 UniId: uniID,
1826 TpInstancePath: tpPath,
1827 GemPortId: gemPortID,
1828 }
1829 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1830
1831 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301832 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1833 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001834 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1835 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301836 "onu-id": onuDev.deviceID,
1837 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001838 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301839 }
khenaidoo106c61a2021-08-11 18:05:46 -04001840
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301842 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001843 "msg": delGemPortMsg,
1844 "from-adapter": f.deviceHandler.device.Type,
1845 "to-adapter": onuDev.deviceType,
1846 "device-id": f.deviceHandler.device.Id,
1847 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 return nil
1849}
1850
Neha Sharma96b7bf22020-06-15 10:37:32 +00001851func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1852 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301853 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001854 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301855 log.Fields{
1856 "intf-id": intfID,
1857 "onu-id": onuID,
1858 "uni-id": uniID,
1859 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001860 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301861 }
1862
khenaidoodc2116e2021-10-19 17:33:19 -04001863 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001864 DeviceId: onuDev.deviceID,
1865 UniId: uniID,
1866 TpInstancePath: tpPath,
1867 AllocId: allocID,
1868 }
1869
Neha Sharma96b7bf22020-06-15 10:37:32 +00001870 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301871 log.Fields{
1872 "msg": *delTcontMsg,
1873 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001874
1875 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301876 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1877 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001878 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1879 "to-adapter": onuDev.adapterEndpoint,
1880 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301881 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001882 "device-id": f.deviceHandler.device.Id}, err)
1883
Girish Gowdra6b130582019-11-20 16:45:20 +05301884 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001885 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301886 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001887 "msg": delTcontMsg,
1888 "device-id": f.deviceHandler.device.Id,
1889 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301890 return nil
1891}
1892
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301893//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001894// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001895func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001896 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001897
1898 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001899
Girish Gowdraa482f272021-03-24 23:04:19 -07001900 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001901 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001902 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1903 log.Fields{
1904 "tpPath": tpPath,
1905 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001906
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001907 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001908 if err != nil || techprofileInst == nil {
1909 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1910 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1911 if childDevice == nil {
1912 // happens when subscriber un-provision is immediately followed by child device delete
1913 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1914 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1915 return nil
1916 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001917 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1918 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001919 log.Fields{
1920 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001921 "path": tpPath}, err).Log()
1922 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001923 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001924
1925 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001926 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001927 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001928 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1929 gemPortID := gemPort.GemportId
yasin sapli9e4c5092022-02-01 13:52:33 +00001930 used := f.resourceMgr.IsGemPortUsedByAnotherFlow(gemPortID, flowID)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001931 if used {
yasin saplibddc2d72022-02-08 13:10:17 +00001932 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
yasin sapli9e4c5092022-02-01 13:52:33 +00001933 if err != nil {
1934 return err
1935 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001936 for i, flowIDinMap := range flowIDs {
1937 if flowIDinMap == flowID {
1938 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001939 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001940 return err
1941 }
1942 break
1943 }
1944 }
1945 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1946 log.Fields{
1947 "gemport-id": gemPortID,
1948 "usedByFlows": flowIDs,
1949 "currentFlow": flowID,
1950 "device-id": f.deviceHandler.device.Id})
1951 allGemPortsFree = false
1952 }
1953 }
1954 if !allGemPortsFree {
1955 return nil
1956 }
1957 }
1958
1959 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 -08001960
1961 // 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 +00001962 switch techprofileInst := techprofileInst.(type) {
1963 case *tp_pb.TechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00001964 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001965 logger.Warn(ctx, err)
1966 }
1967 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1968 logger.Warn(ctx, err)
1969 }
1970
1971 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1972 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001973 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001974
yasin saplibddc2d72022-02-08 13:10:17 +00001975 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001976 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1977 log.Fields{
1978 "err": err,
1979 "intf": intfID,
1980 "onu-id": onuID,
1981 "uni-id": uniID,
1982 "device-id": f.deviceHandler.device.Id,
1983 "gemport-id": gemPortID})
1984 }
1985
1986 }
1987 // Remove queues at OLT in upstream and downstream direction
1988 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1989 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1990 logger.Warn(ctx, err)
1991 }
1992 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1993 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1994 logger.Warn(ctx, err)
1995 }
1996 }
1997
1998 switch techprofileInst := techprofileInst.(type) {
1999 case *tp_pb.TechProfileInstance:
2000 // 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 +01002001 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2002 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2003 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002004 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002005 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002006 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002007 logger.Warn(ctx, err)
2008 }
2009 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002010 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002011 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002012 } else {
2013 // just remove meter reference for the upstream direction for the current pon/onu/uni
2014 // 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
2015 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2016 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002017 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002018 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2019 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002020 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002021 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002022
Girish Gowdraf3728b12022-02-02 21:46:51 -08002023 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2024 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002025 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002026 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2027 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002028 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002029 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002030 case *tp_pb.EponTechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00002031 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002032 logger.Warn(ctx, err)
2033 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002034 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002035 logger.Warn(ctx, err)
2036 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002037 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002038 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002039 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302040 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002041 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302042 "onu-id": onuID,
2043 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002045 "alloc-id": techprofileInst.AllocId,
2046 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002047 }
yasin saplibddc2d72022-02-08 13:10:17 +00002048 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 default:
2050 logger.Errorw(ctx, "error-unknown-tech",
2051 log.Fields{
2052 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002053 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002054
2055 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2056 switch techprofileInst := techprofileInst.(type) {
2057 case *tp_pb.TechProfileInstance:
2058 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2059 // Delete the gem port on the ONU.
2060 if sendDeleteGemRequest {
2061 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2062 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2063 log.Fields{
2064 "err": err,
2065 "intfID": intfID,
2066 "onu-id": onuID,
2067 "uni-id": uniID,
2068 "device-id": f.deviceHandler.device.Id,
2069 "gemport-id": gemPort.GemportId})
2070 }
yasin saplibddc2d72022-02-08 13:10:17 +00002071 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002072 }
2073 }
2074 }
2075
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302076 return nil
2077}
2078
David K. Bainbridge794735f2020-02-11 21:01:37 -08002079// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002080func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002081 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302082 log.Fields{
2083 "flowDirection": flowDirection,
2084 "flow": *flow,
2085 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002086
2087 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002088 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002089 }
2090
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302091 var ethType, ipProto, inPort uint32
2092 for _, field := range flows.GetOfbFields(flow) {
2093 if field.Type == flows.IP_PROTO {
2094 ipProto = field.GetIpProto()
2095 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2096 } else if field.Type == flows.ETH_TYPE {
2097 ethType = field.GetEthType()
2098 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2099 } else if field.Type == flows.IN_PORT {
2100 inPort = field.GetPort()
2101 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2102 }
2103 }
2104 portType := plt.IntfIDToPortTypeName(inPort)
2105 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2106 (portType == voltha.Port_ETHERNET_NNI) {
2107 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2108 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2109 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2110 // No more processing needed for trap from nni flows.
2111 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302112
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302113 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302114 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002115 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002116 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302117 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002118 onuID := int32(onu)
2119 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002120 tpID, err := getTpIDFromFlow(ctx, flow)
2121 if err != nil {
2122 return olterrors.NewErrNotFound("tp-id",
2123 log.Fields{
2124 "flow": flow,
2125 "intf-id": Intf,
2126 "onu-id": onuID,
2127 "uni-id": uniID,
2128 "device-id": f.deviceHandler.device.Id}, err)
2129 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302130
Neha Sharma96b7bf22020-06-15 10:37:32 +00002131 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302132 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002133 "flow-id": flow.Id,
2134 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302135 "onu-id": onuID,
2136 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302137
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002138 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2139 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002140 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2141 return err
2142 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002143
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002144 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002145 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2146 "flow-id": flow.Id,
2147 "device-id": f.deviceHandler.device.Id,
2148 "onu-id": onuID,
2149 "intf": Intf,
2150 "err": err,
2151 })
2152 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302153 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002154
Girish Gowdra82c80982021-03-26 16:22:02 -07002155 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +00002156 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002157 return err
2158 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002159 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002160}
2161
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002162//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002163func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002164
Matteo Scandolof16389e2021-05-18 00:47:08 +00002165 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302166 var direction string
2167 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002168
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302169 for _, action := range flows.GetActions(flow) {
2170 if action.Type == flows.OUTPUT {
2171 if out := action.GetOutput(); out != nil {
2172 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002173 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302174 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002175 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002176 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002177 }
2178 }
2179 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002180
2181 if flows.HasGroup(flow) {
2182 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002183 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002184 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302185 direction = Upstream
2186 } else {
2187 direction = Downstream
2188 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302189
Girish Gowdracefae192020-03-19 18:14:10 -07002190 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002191 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002192
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002193 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002194}
2195
Esin Karamanae41e2b2019-12-17 18:13:13 +00002196//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2197func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002198 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002199 if ethType, ok := classifierInfo[EthType]; ok {
2200 if ethType.(uint32) == IPv4EthType {
2201 if ipProto, ok := classifierInfo[IPProto]; ok {
2202 if ipProto.(uint32) == IgmpProto {
2203 return true
2204 }
2205 }
2206 }
2207 }
2208 }
2209 return false
2210}
2211
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002212// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002213func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002214 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2215 // The device itself is going to be reset as part of deletion. So nothing to be done.
2216 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2217 return nil
2218 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002219 // Step1 : Fill flowControlBlock
2220 // Step2 : Push the flowControlBlock to ONU channel
2221 // Step3 : Wait on response channel for response
2222 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002223 startTime := time.Now()
2224 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002225 errChan := make(chan error)
2226 flowCb := flowControlBlock{
2227 ctx: ctx,
2228 addFlow: addFlow,
2229 flow: flow,
2230 flowMetadata: flowMetadata,
2231 errChan: &errChan,
2232 }
2233 inPort, outPort := getPorts(flow)
2234 var onuID uint32
2235 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002236 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002237 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002238 if f.flowHandlerRoutineActive[onuID] {
2239 // inPort or outPort is InvalidPort for trap-from-nni flows.
2240 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2241 // Send the flowCb on the ONU flow channel
2242 f.incomingFlows[onuID] <- flowCb
2243 // Wait on the channel for flow handlers return value
2244 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002245 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002246 return err
2247 }
2248 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2249 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002250}
2251
2252// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2253// 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 -07002254func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002255 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002256 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002257 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002258 // block on the channel to receive an incoming flow
2259 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002260 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002261 if flowCb.addFlow {
2262 logger.Info(flowCb.ctx, "adding-flow-start")
2263 startTime := time.Now()
2264 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2265 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2266 // Pass the return value over the return channel
2267 *flowCb.errChan <- err
2268 } else {
2269 logger.Info(flowCb.ctx, "removing-flow-start")
2270 startTime := time.Now()
2271 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2272 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2273 // Pass the return value over the return channel
2274 *flowCb.errChan <- err
2275 }
2276 case <-stopHandler:
2277 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2278 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002279 }
2280 }
2281}
2282
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002283// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002284func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002285 for i, v := range f.stopFlowHandlerRoutine {
2286 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002287 select {
2288 case v <- true:
2289 case <-time.After(time.Second * 5):
2290 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2291 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002292 }
2293 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002294 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002295 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2296}
2297
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002298// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302299// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002300func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002301 classifierInfo := make(map[string]interface{})
2302 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002303 var UsMeterID uint32
2304 var DsMeterID uint32
2305
Neha Sharma96b7bf22020-06-15 10:37:32 +00002306 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302307 log.Fields{
2308 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002309 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002310 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002311
Neha Sharma96b7bf22020-06-15 10:37:32 +00002312 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002313 if err != nil {
2314 // Error logging is already done in the called function
2315 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002316 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302317 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002318
Esin Karamanccb714b2019-11-29 15:02:06 +00002319 if flows.HasGroup(flow) {
2320 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002321 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002322 }
2323
manikkaraj k17652a72019-05-06 09:06:36 -04002324 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002325 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002326 if err != nil {
2327 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002328 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002329 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002330
Neha Sharma96b7bf22020-06-15 10:37:32 +00002331 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302332 log.Fields{
2333 "classifierinfo_inport": classifierInfo[InPort],
2334 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002335 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002336
Humera Kouser94d7a842019-08-25 19:04:32 -04002337 if ethType, ok := classifierInfo[EthType]; ok {
2338 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002340 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002341 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002342 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002343 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002344 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2345 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2346 }
2347 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002348 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002349 if ipProto, ok := classifierInfo[IPProto]; ok {
2350 if ipProto.(uint32) == IPProtoDhcp {
2351 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302352 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002353 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002354 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002355 }
2356 }
2357 }
2358 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002359 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002360 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002361 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002362 }
A R Karthick1f85b802019-10-11 05:06:05 +00002363
yasin saplibddc2d72022-02-08 13:10:17 +00002364 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002365
Girish Gowdra6071f382021-12-14 12:52:04 +05302366 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002367 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302368 return olterrors.NewErrNotFound("tpid-for-flow",
2369 log.Fields{
2370 "flow": flow,
2371 "intf-id": IntfID,
2372 "onu-id": onuID,
2373 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002375 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302376 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302377 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302378 "intf-id": intfID,
2379 "onu-id": onuID,
2380 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002381 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002382 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302384 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2385 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2386 return err
2387 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002388 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002389 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002390 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302391 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2392 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2393 return err
2394 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002395 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302396 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002397}
Girish Gowdra3d633032019-12-10 16:37:05 +05302398
Esin Karamanccb714b2019-11-29 15:02:06 +00002399// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002400func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302401 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002402 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302403 "classifier-info": classifierInfo,
2404 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002405
Esin Karaman65409d82020-03-18 10:58:18 +00002406 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002407 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002408 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002409 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002410
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002411 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002412
David K. Bainbridge794735f2020-02-11 21:01:37 -08002413 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002414
yasin saplibddc2d72022-02-08 13:10:17 +00002415 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002416 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002417 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002418 return nil
yasin saplid0566272021-12-21 09:10:30 +00002419 } else if err != nil {
2420 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2421 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2422 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002423 }
yasin saplid0566272021-12-21 09:10:30 +00002424
David K. Bainbridge794735f2020-02-11 21:01:37 -08002425 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2426 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002427 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002428 }
2429 groupID := actionInfo[GroupID].(uint32)
2430 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002431 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002432 FlowType: Multicast,
2433 NetworkIntfId: int32(networkInterfaceID),
2434 GroupId: groupID,
2435 Classifier: classifierProto,
2436 Priority: int32(flow.Priority),
2437 Cookie: flow.Cookie}
2438
Kent Hagermane6ff1012020-07-14 15:07:53 -04002439 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002440 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002441 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002442 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002443 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002444 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002445 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002446 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002447 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002448 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002449 //cached group can be removed now
2450 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002451 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002452 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002453 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002454
David K. Bainbridge794735f2020-02-11 21:01:37 -08002455 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002456}
2457
Esin Karaman65409d82020-03-18 10:58:18 +00002458//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2459func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2460 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002461 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002462 if err != nil {
2463 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2464 }
2465 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002466 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002467
2468 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2469 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002470}
2471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002472//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002473func (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 -07002474
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302476 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302478 log.Fields{
2479 "intf-id": intfID,
2480 "onu-id": onuID,
2481 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002482 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302483 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002485
yasin saplibddc2d72022-02-08 13:10:17 +00002486 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002487 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002488 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002489 UniId: uniID,
2490 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002491 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002492 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002493 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002494
2495 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2496 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302497 return olterrors.NewErrCommunication("send-techprofile-download-request",
2498 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002499 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302500 "to-adapter": onuDev.deviceType,
2501 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002502 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002503 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002504 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302505 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302506}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002507
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002508//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302509func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002510 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002511
2512 if packetIn.IntfType == "pon" {
2513 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002514 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002515 onuID, uniID := packetIn.OnuId, packetIn.UniId
2516 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 +00002517
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002518 if packetIn.PortNo != 0 {
2519 logicalPortNum = packetIn.PortNo
2520 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002521 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002522 }
2523 // 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 +00002524 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002525 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002526 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002527 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002528
2529 if logger.V(log.DebugLevel) {
2530 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2531 log.Fields{
2532 "logical-port-num": logicalPortNum,
2533 "intf-type": packetIn.IntfType,
2534 "packet": hex.EncodeToString(packetIn.Pkt),
2535 })
2536 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002537 return logicalPortNum, nil
2538}
2539
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002540//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002541func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002542 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002543
2544 ctag, priority, err := getCTagFromPacket(ctx, packet)
2545 if err != nil {
2546 return 0, err
2547 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302548
Esin Karaman7fb80c22020-07-16 14:23:33 +00002549 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002550 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002551 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002552 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002553 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302554 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002555 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302556 log.Fields{
2557 "pktinkey": pktInkey,
2558 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002559
2560 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002561 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302562 //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 +00002563 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302564 if err == nil {
2565 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002566 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302567 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002568 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002569 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302570 log.Fields{
2571 "pktinkey": pktInkey,
2572 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302573 return gemPortID, nil
2574 }
2575 }
Shrey Baid26912972020-04-16 21:02:31 +05302576 return uint32(0), olterrors.NewErrNotFound("gem-port",
2577 log.Fields{
2578 "pktinkey": pktInkey,
2579 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002580
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002581}
2582
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002583func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2584 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002585 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002586 classifier[PacketTagType] = DoubleTag
2587 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588 /* We manage flowId resource pool on per PON port basis.
2589 Since this situation is tricky, as a hack, we pass the NNI port
2590 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002591 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002592 on NNI port, use onu_id as -1 (invalid)
2593 ****************** CAVEAT *******************
2594 This logic works if the NNI Port Id falls within the same valid
2595 range of PON Port Ids. If this doesn't work for some OLT Vendor
2596 we need to have a re-look at this.
2597 *********************************************
2598 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002599 onuID := -1
2600 uniID := -1
2601 gemPortID := -1
2602 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002603 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302604 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302605 return olterrors.NewErrNotFound("nni-intreface-id",
2606 log.Fields{
2607 "classifier": classifier,
2608 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002609 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302610 }
2611
yasin saplibddc2d72022-02-08 13:10:17 +00002612 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002613 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002614 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002615 return nil
yasin saplid0566272021-12-21 09:10:30 +00002616 } else if err != nil {
2617 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2618 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2619 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002620 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002621
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002622 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2623 log.Fields{
2624 "classifier": classifier,
2625 "action": action,
2626 "flowId": logicalFlow.Id,
2627 "intf-id": networkInterfaceID})
2628
David K. Bainbridge794735f2020-02-11 21:01:37 -08002629 classifierProto, err := makeOpenOltClassifierField(classifier)
2630 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002631 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002632 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002633 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002634 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002635 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002636 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002637 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002638 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002639 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2640 OnuId: int32(onuID), // OnuId not required
2641 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002642 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002643 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002644 AllocId: int32(allocID), // AllocId not used
2645 NetworkIntfId: int32(networkInterfaceID),
2646 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002647 Classifier: classifierProto,
2648 Action: actionProto,
2649 Priority: int32(logicalFlow.Priority),
2650 Cookie: logicalFlow.Cookie,
2651 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002652 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002653 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002654 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002655 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002656 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002657}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002658
Esin Karamanae41e2b2019-12-17 18:13:13 +00002659//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2660func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2661 var packetType string
2662 ovid, ivid := false, false
2663 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2664 vid := vlanID & VlanvIDMask
2665 if vid != ReservedVlan {
2666 ovid = true
2667 }
2668 }
2669 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2670 vid := uint32(metadata)
2671 if vid != ReservedVlan {
2672 ivid = true
2673 }
2674 }
2675 if ovid && ivid {
2676 packetType = DoubleTag
2677 } else if !ovid && !ivid {
2678 packetType = Untagged
2679 } else {
2680 packetType = SingleTag
2681 }
2682 return packetType
2683}
2684
2685//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002686func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002687 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002688 action := make(map[string]interface{})
2689 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2690 action[TrapToHost] = true
2691 /* We manage flowId resource pool on per PON port basis.
2692 Since this situation is tricky, as a hack, we pass the NNI port
2693 index (network_intf_id) as PON port Index for the flowId resource
2694 pool. Also, there is no ONU Id available for trapping packets
2695 on NNI port, use onu_id as -1 (invalid)
2696 ****************** CAVEAT *******************
2697 This logic works if the NNI Port Id falls within the same valid
2698 range of PON Port Ids. If this doesn't work for some OLT Vendor
2699 we need to have a re-look at this.
2700 *********************************************
2701 */
2702 onuID := -1
2703 uniID := -1
2704 gemPortID := -1
2705 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002706 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002707 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302708 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002709 "classifier": classifier,
2710 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002711 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002712 }
yasin saplibddc2d72022-02-08 13:10:17 +00002713 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002714 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002715 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002716 return nil
yasin saplid0566272021-12-21 09:10:30 +00002717 } else if err != nil {
2718 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2719 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2720 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002721 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002722
David K. Bainbridge794735f2020-02-11 21:01:37 -08002723 classifierProto, err := makeOpenOltClassifierField(classifier)
2724 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002725 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002726 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002727 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002728 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002729 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002730 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002731 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002732 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002733 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2734 OnuId: int32(onuID), // OnuId not required
2735 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002736 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002737 FlowType: Downstream,
2738 AllocId: int32(allocID), // AllocId not used
2739 NetworkIntfId: int32(networkInterfaceID),
2740 GemportId: int32(gemPortID), // GemportId not used
2741 Classifier: classifierProto,
2742 Action: actionProto,
2743 Priority: int32(logicalFlow.Priority),
2744 Cookie: logicalFlow.Cookie,
2745 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002746 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002747 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002749 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002750
David K. Bainbridge794735f2020-02-11 21:01:37 -08002751 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002752}
2753
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2755 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302756 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002757 }
2758 if Dir == tp_pb.Direction_UPSTREAM {
2759 return "upstream", nil
2760 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2761 return "downstream", nil
2762 }
2763 return "", nil
2764}
2765
Kent Hagermane6ff1012020-07-14 15:07:53 -04002766// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302767func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002768 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002769 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002770 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002771 intfID := args[IntfID]
2772 onuID := args[OnuID]
2773 uniID := args[UniID]
2774 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002775 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002776 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002777 gemToAes := make(map[uint32]bool)
2778
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002779 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002780 var direction = tp_pb.Direction_UPSTREAM
2781 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002782 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002783 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002784 attributes = TpInst.UpstreamGemPortAttributeList
2785 } else {
2786 attributes = TpInst.DownstreamGemPortAttributeList
2787 direction = tp_pb.Direction_DOWNSTREAM
2788 }
2789 default:
2790 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002791 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002792 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002793
2794 if len(gemPorts) == 1 {
2795 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002796 gemPortID = gemPorts[0]
2797 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002798 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2799 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002800 pBitMap := attributes[idx].PbitMap
2801 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2802 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2803 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002804 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002805 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2806 if pbitSet == pbit1 {
2807 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2808 pbitToGem[pcp] = gemID
2809 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002810 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002811 }
2812 }
2813 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002814 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2815 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2816 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002817 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818 }
2819
Gamze Abaka7650be62021-02-26 10:50:36 +00002820 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2821 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2822
salmansiddiqui7ac62132019-08-22 03:58:50 +00002823 if ipProto, ok := classifierInfo[IPProto]; ok {
2824 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002825 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002826 "tp-id": tpID,
2827 "alloc-id": allocID,
2828 "intf-id": intfID,
2829 "onu-id": onuID,
2830 "uni-id": uniID,
2831 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002832 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002833 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002834 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002835 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2836 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002837 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002838 }
2839
Girish Gowdra32625212020-04-29 11:26:35 -07002840 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002841 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302842 log.Fields{
2843 "intf-id": intfID,
2844 "onu-id": onuID,
2845 "uni-id": uniID,
2846 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002848 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002849 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2850 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002851 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002852 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002853 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002854 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002855 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 }
2857 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002858 if ethType.(uint32) == EapEthType {
2859 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002860 "intf-id": intfID,
2861 "onu-id": onuID,
2862 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002863 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002864 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002865 var vlanID uint32
2866 if val, ok := classifierInfo[VlanVid]; ok {
2867 vlanID = (val.(uint32)) & VlanvIDMask
2868 } else {
2869 vlanID = DefaultMgmtVlan
2870 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002871 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002872 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002873 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2874 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002875 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002876 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002877 } else if ethType.(uint32) == PPPoEDEthType {
2878 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2879 "tp-id": tpID,
2880 "alloc-id": allocID,
2881 "intf-id": intfID,
2882 "onu-id": onuID,
2883 "uni-id": uniID,
2884 })
2885 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002886 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002887 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002888 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2889 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002890 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002891 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002893 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002894 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002895 "intf-id": intfID,
2896 "onu-id": onuID,
2897 "uni-id": uniID,
2898 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002899 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002900 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002901 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002902 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2903 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002904 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002905 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002906 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002907 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002908 "intf-id": intfID,
2909 "onu-id": onuID,
2910 "uni-id": uniID,
2911 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002912 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002913 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002914 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002915 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
2916 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002917 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 }
2919 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002920 return olterrors.NewErrInvalidValue(log.Fields{
2921 "intf-id": intfID,
2922 "onu-id": onuID,
2923 "uni-id": uniID,
2924 "classifier": classifierInfo,
2925 "action": actionInfo,
2926 "flow": flow},
2927 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
2929 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002930 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002931 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002932 logger.Warn(ctx, err)
2933 }
2934 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002935 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936}
2937
Gamze Abakacb0e6772021-06-10 08:32:12 +00002938func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002939 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2940 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2941 tpInstances := f.techprofile.FindAllTpInstances(ctx, f.deviceHandler.device.Id, sq.tpID, sq.intfID, sq.onuID).([]tp_pb.TechProfileInstance)
Girish Gowdra54934262019-11-13 14:19:55 +05302942 for i := 0; i < len(tpInstances); i++ {
2943 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002944 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002945 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002946 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002947 log.Fields{
2948 "device-id": f.deviceHandler.device.Id,
2949 "intfID": sq.intfID,
2950 "onuID": sq.onuID,
2951 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002952 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002953 })
2954 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302955 }
2956 }
2957 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002958 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002959}
2960
Neha Sharma96b7bf22020-06-15 10:37:32 +00002961func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002962 for _, field := range flows.GetOfbFields(flow) {
2963 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002965 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002966 } else if field.Type == flows.ETH_DST {
2967 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002969 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002970 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002971 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002972 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002975 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05302976 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
2977 if field.GetVlanVid() != ReservedVlan {
2978 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
2979 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
2980 }
Scott Baker355d1742019-10-24 10:57:52 -07002981 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002983 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002984 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002985 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002986 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002987 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002988 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002989 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002990 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002991 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002992 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002993 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002994 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002995 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002996 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002997 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002999 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003003 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003004 return
3005 }
3006 }
3007}
3008
Neha Sharma96b7bf22020-06-15 10:37:32 +00003009func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003010 for _, action := range flows.GetActions(flow) {
3011 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003013 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003014 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003015 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003016 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003017 }
Scott Baker355d1742019-10-24 10:57:52 -07003018 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003019 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003020 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003021 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003022 if out := action.GetPush(); out != nil {
3023 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003024 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003025 } else {
3026 actionInfo[PushVlan] = true
3027 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303029 log.Fields{
3030 "push-tpid": actionInfo[TPID].(uint32),
3031 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 }
3033 }
Scott Baker355d1742019-10-24 10:57:52 -07003034 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003035 if out := action.GetSetField(); out != nil {
3036 if field := out.GetField(); field != nil {
3037 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003038 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3041 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 }
3043 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003044 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003046 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003047 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 }
3049 }
3050 return nil
3051}
3052
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003054 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003055 fieldtype := ofbField.GetType()
3056 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003057 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3058 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003060 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003061 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003062 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003063 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3064 pcp := ofbField.GetVlanPcp()
3065 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003066 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003067 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003068 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003069 }
3070 }
3071}
3072
Neha Sharma96b7bf22020-06-15 10:37:32 +00003073func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003074 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003075 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003076 } else {
3077 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003078 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003079 }
3080}
3081
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003083 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003086 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003087 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003088 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303090 log.Fields{
3091 "newinport": classifierInfo[InPort].(uint32),
3092 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303094 return olterrors.NewErrNotFound("child-in-port",
3095 log.Fields{
3096 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3097 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 }
3099 }
3100 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003101 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003103 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003104 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003105 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303107 log.Fields{
3108 "newoutport": actionInfo[Output].(uint32),
3109 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003110 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303111 return olterrors.NewErrNotFound("out-port",
3112 log.Fields{
3113 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3114 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003115 }
3116 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003117 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003118 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003119 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303121 log.Fields{
3122 "newinport": actionInfo[Output].(uint32),
3123 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303125 return olterrors.NewErrNotFound("nni-port",
3126 log.Fields{
3127 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3128 "in-port": classifierInfo[InPort].(uint32),
3129 "out-port": actionInfo[Output].(uint32),
3130 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003131 }
3132 }
3133 }
3134 return nil
3135}
Gamze Abakafee36392019-10-03 11:17:24 +00003136
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003138 /* Metadata 8 bytes:
3139 Most Significant 2 Bytes = Inner VLAN
3140 Next 2 Bytes = Tech Profile ID(TPID)
3141 Least Significant 4 Bytes = Port ID
3142 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3143 subscriber related flows.
3144 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003146 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003147 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003148 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003150 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003151}
3152
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003153func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003154 for _, sliceElement := range slice {
3155 if sliceElement == item {
3156 return slice
3157 }
3158 }
3159 return append(slice, item)
3160}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303161
3162// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003163func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303164
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003165 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303166 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003167 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003168 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003170 log.Fields{
3171 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003172 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003173 return uint32(0), err
3174 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003175 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303176 return intfID, nil
3177 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003178 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003179 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003181 log.Fields{
3182 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003183 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003184 return uint32(0), err
3185 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303187 return intfID, nil
3188 }
3189 return uint32(0), nil
3190}
3191
3192// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003193func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3194 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3195 if err != nil {
3196 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3197 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3198 return
3199 }
3200 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003201
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003202 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003203 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003204 f.packetInGemPortLock.RUnlock()
3205
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303206 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003207 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003208 logger.Infow(ctx, "pktin-key/value-found-in-cache--no-need-to-update-kv--assume-both-in-sync",
Shrey Baid26912972020-04-16 21:02:31 +05303209 log.Fields{
3210 "pktinkey": pktInkey,
3211 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003212 return
3213 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303214 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003215 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003216 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003217 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003218
npujarec5762e2020-01-01 14:08:48 +05303219 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003220 logger.Infow(ctx, "pktin-key-not-found-in-local-cache-value-is-different--updating-cache-and-kv-store",
Shrey Baid26912972020-04-16 21:02:31 +05303221 log.Fields{
3222 "pktinkey": pktInkey,
3223 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303224}
3225
Esin Karaman7fb80c22020-07-16 14:23:33 +00003226//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3227func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3228 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003229 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003230 return 0, 0, errors.New("invalid packet length")
3231 }
3232 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3233 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3234
3235 var index int8
3236 if outerEthType == 0x8100 {
3237 if innerEthType == 0x8100 {
3238 // q-in-q 802.1ad or 802.1q double tagged packet.
3239 // get the inner vlanId
3240 index = 18
3241 } else {
3242 index = 14
3243 }
3244 priority := (packet[index] >> 5) & 0x7
3245 //13 bits composes vlanId value
3246 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3247 return vlan, priority, nil
3248 }
3249 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3250 return 0, 0, nil
3251}
3252
Girish Gowdra9602eb42020-09-09 15:50:39 -07003253//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3254// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003255func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003256 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003257 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3258 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003259 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003260 "flow-id": flow.Id,
3261 "device-id": f.deviceHandler.device.Id})
3262 // Remove from device
3263 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3264 // DKB
3265 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3266 log.Fields{
3267 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003268 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003269 return err
3270 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003271
3272 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003273}
3274
khenaidoodc2116e2021-10-19 17:33:19 -04003275func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003276 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003277 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003278 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003279 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003280 }
3281
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003282 switch tpInst := tpInst.(type) {
3283 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003284 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003285 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003286 DeviceId: onuDeviceID,
3287 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003288 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003289 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003290 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003291 case *tp_pb.EponTechProfileInstance:
3292 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003293 DeviceId: onuDeviceID,
3294 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003295 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003296 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003297 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003298 default:
3299 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003300 }
khenaidoodc2116e2021-10-19 17:33:19 -04003301 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003302 DeviceId: onuDeviceID,
3303 UniId: uniID,
3304 TpInstancePath: tpPath,
3305 TechTpInstance: nil,
3306 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003307}
3308
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003309// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3310func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3311
3312 intfID := sq.intfID
3313 onuID := sq.onuID
3314 uniID := sq.uniID
3315 tpID := sq.tpID
3316
3317 var reverseDirection string
3318 if sq.direction == tp_pb.Direction_UPSTREAM {
3319 reverseDirection = "downstream"
3320 } else {
3321 reverseDirection = "upstream"
3322 }
3323
3324 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003325 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003326 return
3327 }
3328
3329 // revert-delete tech-profile instance and delete tech profile id for onu
3330 logger.Warnw(ctx, "reverting-tech-profile-instance-and-tech-profile-id-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "tp-id": tpID})
3331 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3332 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003333 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003334
3335 // free gem/alloc
3336 switch techprofileInst := sq.tpInst.(type) {
3337 case *tp_pb.TechProfileInstance:
3338 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003339 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003340 }
yasin saplibddc2d72022-02-08 13:10:17 +00003341 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003342 }
3343}
3344
3345// revertSchduler is called when CreateQueues request fails
3346func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3347 // revert scheduler
3348 logger.Warnw(ctx, "reverting-scheduler-for-onu", log.Fields{"intf-id": sq.intfID, "onu-id": sq.onuID, "uni-id": sq.uniID, "tp-id": sq.tpID})
3349 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3350 IntfId: sq.intfID, OnuId: sq.onuID,
3351 UniId: sq.uniID, PortNo: sq.uniPort,
3352 TrafficScheds: TrafficSched})
3353}
Girish Gowdra6071f382021-12-14 12:52:04 +05303354
3355// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3356func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00003357 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303358 if err != nil {
3359 return olterrors.NewErrNotFound("meter",
3360 log.Fields{"intf-id": intfID,
3361 "onu-id": onuID,
3362 "uni-id": uniID,
3363 "device-id": f.deviceHandler.device.Id}, err)
3364 }
3365
3366 if meterInfo != nil {
3367 // If RefCnt become 0 clear the meter information from the DB.
3368 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003369 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303370 return err
3371 }
3372 } else if meterInfo.MeterID != meterID {
3373 logger.Errorw(ctx, "meter-mismatch-for-direction",
3374 log.Fields{"direction": direction,
3375 "kv-store-meter-id": meterInfo.MeterID,
3376 "meter-id-in-flow": meterID,
3377 "device-id": f.deviceHandler.device.Id})
3378 return olterrors.NewErrInvalidValue(log.Fields{
3379 "unsupported": "meter-id",
3380 "kv-store-meter-id": meterInfo.MeterID,
3381 "meter-id-in-flow": meterID,
3382 "device-id": f.deviceHandler.device.Id}, nil)
3383 }
3384 }
3385 return nil
3386}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003387
3388func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3389 /* After we successfully remove the scheduler configuration on the OLT device,
3390 * delete the meter id on the KV store.
3391 */
yasin saplibddc2d72022-02-08 13:10:17 +00003392 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003393 if err != nil {
3394 return olterrors.NewErrAdapter("unable-to-remove-meter",
3395 log.Fields{
3396 "onu": sq.onuID,
3397 "device-id": f.deviceHandler.device.Id,
3398 "intf-id": sq.intfID,
3399 "onu-id": sq.onuID,
3400 "uni-id": sq.uniID,
3401 "uni-port": sq.uniPort}, err)
3402 }
3403 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3404 log.Fields{
3405 "dir": direction,
3406 "device-id": f.deviceHandler.device.Id,
3407 "intf-id": sq.intfID,
3408 "onu-id": sq.onuID,
3409 "uni-id": sq.uniID,
3410 "uni-port": sq.uniPort})
3411 return err
3412}