blob: 81f7fcbfbdd37105946ec5cf21ae79927520c288 [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
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700227 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700228 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
manikkaraj kbf256be2019-03-25 00:13:48 +0530229 return nil
230 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530231 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700232
233 // Create a slice of buffered channels for handling concurrent flows per ONU.
234 // 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 -0700235 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
236 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
237 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700238 for i := range flowMgr.incomingFlows {
239 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800240 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700241 // Spin up a go routine to handling incoming flows (add/remove).
242 // There will be on go routine per ONU.
243 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700244 flowMgr.flowHandlerRoutineActive[i] = true
245 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700247
Esin Karamanccb714b2019-11-29 15:02:06 +0000248 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700249 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000250 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530251 return &flowMgr
252}
253
Kent Hagermane6ff1012020-07-14 15:07:53 -0400254func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700255 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
256 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin sapli9e4c5092022-02-01 13:52:33 +0000257 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700258 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
259 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
260 for _, gemPort := range deviceFlow.PbitToGemport {
yasin sapli9e4c5092022-02-01 13:52:33 +0000261 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700262 return err
263 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700264 }
Gamze Abakafee36392019-10-03 11:17:24 +0000265 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700266 return nil
267}
268
Girish Gowdra9602eb42020-09-09 15:50:39 -0700269func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000270 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400271 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000272 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530273 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700274 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530275
Neha Sharma96b7bf22020-06-15 10:37:32 +0000276 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530277 "device-id": f.deviceHandler.device.Id,
278 "intf-id": intfID,
279 "onu-id": onuID,
280 "uni-id": uniID,
281 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700282 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530283 "action": actionInfo,
284 "usmeter-iD": UsMeterID,
285 "dsmeter-iD": DsMeterID,
286 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400287 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
288 // is because the flow is an NNI flow and there would be no onu resources associated with it
289 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400290 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200291 cause := "no-onu-id-for-flow"
292 fields := log.Fields{
293 "onu": onuID,
294 "port-no": portNo,
295 "classifer": classifierInfo,
296 "action": actionInfo,
297 "device-id": f.deviceHandler.device.Id}
298 logger.Errorw(ctx, cause, fields)
299 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530300 }
301
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700302 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000303 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530304 "uni": uni,
305 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530306
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700307 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
308 "device-id": f.deviceHandler.device.Id,
309 "intf-id": intfID,
310 "onu-id": onuID,
311 "uni-id": uniID,
312 "port-no": portNo,
313 "classifier": classifierInfo,
314 "action": actionInfo,
315 "usmeter-id": UsMeterID,
316 "dsmeter-id": DsMeterID,
317 "tp-id": TpID})
318 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
319 if allocID == 0 || gemPorts == nil || TpInst == nil {
320 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
321 return olterrors.NewErrNotFound(
322 "alloc-id-gem-ports-tp-unavailable",
323 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400324 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700325 args := make(map[string]uint32)
326 args[IntfID] = intfID
327 args[OnuID] = onuID
328 args[UniID] = uniID
329 args[PortNo] = portNo
330 args[AllocID] = allocID
331
332 /* Flows can be added specific to gemport if p-bits are received.
333 * If no pbit mentioned then adding flows for all gemports
334 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000335 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530336}
337
salmansiddiqui7ac62132019-08-22 03:58:50 +0000338// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800339// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530340func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400341
Girish Gowdraf3728b12022-02-02 21:46:51 -0800342 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530343 log.Fields{"dir": sq.direction,
344 "intf-id": sq.intfID,
345 "onu-id": sq.onuID,
346 "uni-id": sq.uniID,
347 "tp-id": sq.tpID,
348 "meter-id": sq.meterID,
349 "tp-inst": sq.tpInst,
350 "flowmetadata": sq.flowMetadata,
351 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400352
Girish Gowdra6071f382021-12-14 12:52:04 +0530353 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000354 if err != nil {
355 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400356 }
357
Girish Gowdraf3728b12022-02-02 21:46:51 -0800358 var TrafficShaping *tp_pb.TrafficShapingInfo
359 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
360 return olterrors.NewErrInvalidValue(log.Fields{
361 "reason": "invalid-meter-config",
362 "meter-id": sq.meterID,
363 "device-id": f.deviceHandler.device.Id}, nil)
364 }
365
366 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
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 var SchedCfg *tp_pb.SchedulerConfig
374 if sq.direction == tp_pb.Direction_UPSTREAM {
375 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
376 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
377 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
378 }
379 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
380 TrafficSched[0].TechProfileId = sq.tpID
381
Manikkaraj kb1d51442019-07-23 10:41:02 -0400382 /* Lets make a simple assumption that if the meter-id is present on the KV store,
383 * then the scheduler and queues configuration is applied on the OLT device
384 * in the given direction.
385 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530386 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400387 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530388 return olterrors.NewErrNotFound("meter",
389 log.Fields{"intf-id": sq.intfID,
390 "onu-id": sq.onuID,
391 "uni-id": sq.uniID,
392 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400393 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000394
Girish Gowdraf3728b12022-02-02 21:46:51 -0800395 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530396 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800397 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530398 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
Girish Gowdraf3728b12022-02-02 21:46:51 -0800399 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
400 return err
401 }
402
403 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
404 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
405 // Just create gem ports and traffic queues on the current uni for the given service
406 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
407 log.Fields{"intf-id": sq.intfID,
408 "onu-id": sq.onuID,
409 "uni-id": sq.uniID,
410 "tp-id": sq.tpID,
411 "device-id": f.deviceHandler.device.Id})
412 // The upstream scheduler is already created. We only need to create the queues
413 // If there are multiple upstream flows on a given uni, then it is possible that
414 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
415 // TODO: Find better mechanism to not duplicate request.
416 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
417 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
418 log.Fields{"intf-id": sq.intfID,
419 "direction": sq.direction,
420 "device-id": f.deviceHandler.device.Id}, err)
421 }
422 } else {
423 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
424 log.Fields{"intf-id": sq.intfID,
425 "onu-id": sq.onuID,
426 "uni-id": sq.uniID,
427 "tp-id": sq.tpID,
428 "device-id": f.deviceHandler.device.Id})
429 }
430 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400431 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000432
Neha Sharma96b7bf22020-06-15 10:37:32 +0000433 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530434 log.Fields{
435 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530436 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530437 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000438
Girish Gowdraa482f272021-03-24 23:04:19 -0700439 found := false
440 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000441 if sq.flowMetadata != nil {
442 for _, meter := range sq.flowMetadata.Meters {
443 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700444 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700445 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 +0000446 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700447 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530448 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700449 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 break
451 }
452 }
453 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000454 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400455 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700456 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530457 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800458 "reason": "Could-not-get-meterbands-from-flowMetadata",
459 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530460 "meter-id": sq.meterID,
461 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400462 }
Gamze Abaka01174422021-03-10 06:55:27 +0000463
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700464 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530465 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
466 log.Fields{"intf-id": sq.intfID,
467 "direction": sq.direction,
468 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 }
470
salmansiddiqui7ac62132019-08-22 03:58:50 +0000471 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400472 * store the meter id on the KV store, for further reference.
473 */
Girish Gowdra6071f382021-12-14 12:52:04 +0530474 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530475 return olterrors.NewErrAdapter("failed-updating-meter-id",
476 log.Fields{"onu-id": sq.onuID,
477 "meter-id": sq.meterID,
478 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400479 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000480 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530481 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700482 "meter-info": meterInfo,
483 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400484 return nil
485}
486
Girish Gowdraf3728b12022-02-02 21:46:51 -0800487func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
488 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
489 if err != nil {
490 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
491 log.Fields{"intf-id": sq.intfID,
492 "direction": sq.direction,
493 "device-id": f.deviceHandler.device.Id}, err)
494 }
495 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
496 log.Fields{"direction": sq.direction,
497 "traffic-queues": trafficQueues,
498 "device-id": f.deviceHandler.device.Id})
499 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
500 UniId: sq.uniID, PortNo: sq.uniPort,
501 TrafficQueues: trafficQueues,
502 TechProfileId: TrafficSched[0].TechProfileId}
503 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
504 if len(queues.TrafficQueues) > 1 {
505 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
506 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
507 }
508 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
509 }
510 return err
511}
512
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700513func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700514 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000515
516 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530517 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
518 log.Fields{"intf-id": sq.intfID,
519 "direction": sq.direction,
520 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000521 }
522
Gamze Abakacb0e6772021-06-10 08:32:12 +0000523 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
524 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
525 log.Fields{
526 "direction": sq.direction,
527 "TrafficScheds": TrafficSched,
528 "device-id": f.deviceHandler.device.Id,
529 "intfID": sq.intfID,
530 "onuID": sq.onuID,
531 "uniID": sq.uniID})
532 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
533 IntfId: sq.intfID, OnuId: sq.onuID,
534 UniId: sq.uniID, PortNo: sq.uniPort,
535 TrafficScheds: TrafficSched}); err != nil {
536 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
537 }
538 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
539 "direction": sq.direction,
540 "traffic-queues": trafficQueues,
541 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000542 }
543
544 // On receiving the CreateTrafficQueues request, the driver should create corresponding
545 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000546 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530547 log.Fields{"direction": sq.direction,
548 "traffic-queues": trafficQueues,
549 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000550 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
551 UniId: sq.uniID, PortNo: sq.uniPort,
552 TrafficQueues: trafficQueues,
553 TechProfileId: TrafficSched[0].TechProfileId}
554 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
555 if len(queues.TrafficQueues) > 1 {
556 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
557 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
558 }
559 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530560 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000561 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000562 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530563 "direction": sq.direction,
564 "traffic-queues": trafficQueues,
565 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000566
Esin Karamanccb714b2019-11-29 15:02:06 +0000567 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700568 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000569 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700570 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 +0000571 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
572 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000573 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000574 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700575 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 gemPortID: multicastQueuePerPonPort.GemportId,
577 servicePriority: multicastQueuePerPonPort.Priority,
578 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700579 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 //also store the queue info in kv store
Kent Hagermane6ff1012020-07-14 15:07:53 -0400581 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, sq.intfID, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700582 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400583 return err
584 }
Shrey Baid26912972020-04-16 21:02:31 +0530585
Neha Sharma96b7bf22020-06-15 10:37:32 +0000586 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000587 }
588 }
589 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000590 return nil
591}
592
Girish Gowdraf3728b12022-02-02 21:46:51 -0800593// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
594func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
595 var err error
596 logger.Infow(ctx, "removing-queue-in-olt",
597 log.Fields{
598 "direction": sq.direction,
599 "intf-id": sq.intfID,
600 "onu-id": sq.onuID,
601 "uni-id": sq.uniID,
602 "uni-port": sq.uniPort,
603 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400604
Girish Gowdraf3728b12022-02-02 21:46:51 -0800605 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
606 if err != nil {
607 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
608 log.Fields{
609 "intf-id": sq.intfID,
610 "direction": sq.direction,
611 "device-id": f.deviceHandler.device.Id}, err)
612 }
613
614 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
615 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
616 UniId: sq.uniID, PortNo: sq.uniPort,
617 TrafficQueues: TrafficQueues,
618 TechProfileId: sq.tpID}); err != nil {
619 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
620 log.Fields{
621 "intf-id": sq.intfID,
622 "traffic-queues": TrafficQueues,
623 "device-id": f.deviceHandler.device.Id}, err)
624 }
625 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
626
627 return err
628}
629
630// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
631func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400632 var Direction string
633 var SchedCfg *tp_pb.SchedulerConfig
634 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800635 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530636 log.Fields{
637 "direction": sq.direction,
638 "intf-id": sq.intfID,
639 "onu-id": sq.onuID,
640 "uni-id": sq.uniID,
641 "uni-port": sq.uniPort,
642 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000643 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700644 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400645 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000646 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700647 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400648 Direction = "downstream"
649 }
650
Girish Gowdraa482f272021-03-24 23:04:19 -0700651 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 -0400652
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700653 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000654 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000655
Girish Gowdraf3728b12022-02-02 21:46:51 -0800656 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
657 IntfId: sq.intfID, OnuId: sq.onuID,
658 UniId: sq.uniID, PortNo: sq.uniPort,
659 TrafficScheds: TrafficSched}); err != nil {
660 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530661 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800662 "intf-id": sq.intfID,
663 "traffic-schedulers": TrafficSched,
664 "onu-id": sq.onuID,
665 "uni-id": sq.uniID,
666 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000667 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400668
Girish Gowdraf3728b12022-02-02 21:46:51 -0800669 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
670 log.Fields{"device-id": f.deviceHandler.device.Id,
671 "intf-id": sq.intfID,
672 "onu-id": sq.onuID,
673 "uni-id": sq.uniID,
674 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400675
Girish Gowdraf3728b12022-02-02 21:46:51 -0800676 if sq.direction == tp_pb.Direction_UPSTREAM {
677 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
678 // Delete the TCONT on the ONU.
679 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
680 tpPath := f.getTPpath(ctx, sq.intfID, uni, sq.tpID)
681 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
682 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000683 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800684 "intf": sq.intfID,
685 "onu-id": sq.onuID,
686 "uni-id": sq.uniID,
687 "device-id": f.deviceHandler.device.Id,
688 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000689 }
690 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000691
692 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400693 * delete the meter id on the KV store.
694 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800695 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400696 return err
697}
698
Girish Gowdra197acc12021-08-16 10:59:45 -0700699// We are trying to force remove the schedulers and queues here if one exists for the given key.
700// We ignore any errors encountered in the process. The errors most likely are encountered when
701// the schedulers and queues are already cleared for the given key.
702func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
703
704 var schedCfg *tp_pb.SchedulerConfig
705 var err error
706 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
707 log.Fields{
708 "direction": sq.direction,
709 "intf-id": sq.intfID,
710 "onu-id": sq.onuID,
711 "uni-id": sq.uniID,
712 "uni-port": sq.uniPort,
713 "tp-id": sq.tpID,
714 "device-id": f.deviceHandler.device.Id})
715 if sq.direction == tp_pb.Direction_UPSTREAM {
716 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
717 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
718 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
719 }
720
721 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
722 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
723 TrafficSched[0].TechProfileId = sq.tpID
724
725 // Remove traffic queues. Ignore any errors, just log them.
726 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
727 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
728 "direction": sq.direction,
729 "intf-id": sq.intfID,
730 "onu-id": sq.onuID,
731 "uni-id": sq.uniID,
732 "uni-port": sq.uniPort,
733 "tp-id": sq.tpID,
734 "device-id": f.deviceHandler.device.Id,
735 "err": err})
736 } else {
737 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
738 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
739 UniId: sq.uniID, PortNo: sq.uniPort,
740 TrafficQueues: TrafficQueues,
741 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
742 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
743 "direction": sq.direction,
744 "intf-id": sq.intfID,
745 "onu-id": sq.onuID,
746 "uni-id": sq.uniID,
747 "uni-port": sq.uniPort,
748 "tp-id": sq.tpID,
749 "device-id": f.deviceHandler.device.Id,
750 "err": err})
751
752 } else {
753 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
754 "direction": sq.direction,
755 "intf-id": sq.intfID,
756 "onu-id": sq.onuID,
757 "uni-id": sq.uniID,
758 "uni-port": sq.uniPort,
759 "tp-id": sq.tpID})
760 }
761 }
762
763 // Remove traffic schedulers. Ignore any errors, just log them.
764 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
765 IntfId: sq.intfID, OnuId: sq.onuID,
766 UniId: sq.uniID, PortNo: sq.uniPort,
767 TrafficScheds: TrafficSched}); err != nil {
768 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
769 "direction": sq.direction,
770 "intf-id": sq.intfID,
771 "onu-id": sq.onuID,
772 "uni-id": sq.uniID,
773 "uni-port": sq.uniPort,
774 "tp-id": sq.tpID,
775 "device-id": f.deviceHandler.device.Id,
776 "err": err})
777 } else {
778 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
779 "direction": sq.direction,
780 "intf-id": sq.intfID,
781 "onu-id": sq.onuID,
782 "uni-id": sq.uniID,
783 "uni-port": sq.uniPort,
784 "tp-id": sq.tpID})
785 }
786}
787
Gamze Abakafee36392019-10-03 11:17:24 +0000788// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400789func (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 +0000790 var allocIDs []uint32
791 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530792 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530793 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000794 var err error
npujarec5762e2020-01-01 14:08:48 +0530795 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, intfID, onuID, uniID)
796 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, intfID, onuID, uniID)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000797 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530798
Neha Sharma96b7bf22020-06-15 10:37:32 +0000799 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530800 "intf-id": intfID,
801 "onu-id": onuID,
802 "uni-id": uniID,
803 "device-id": f.deviceHandler.device.Id,
804 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530805
Manikkaraj kb1d51442019-07-23 10:41:02 -0400806 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700807 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000808 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000809 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530810 log.Fields{
811 "path": tpPath,
812 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700813 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000814 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530815 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000816 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530817 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700818 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530819 "tp-id": TpID,
820 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000821 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530822 }
Kent Hagermane6ff1012020-07-14 15:07:53 -0400823 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, intfID, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700824 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400825 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530826 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000827 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530828 log.Fields{
829 "uni": uni,
830 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530831 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530832 }
Gamze Abakafee36392019-10-03 11:17:24 +0000833
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700834 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700835 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700836 if UsMeterID != 0 {
837 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
838 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
839 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000840 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700841 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700842 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700843 "onu-id": onuID,
844 "uni-id": uniID,
845 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700846 "meter-id": UsMeterID,
847 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000848 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700849 return 0, nil, nil
850 }
851 }
852 if DsMeterID != 0 {
853 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
854 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
855 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000856 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700857 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700858 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700859 "onu-id": onuID,
860 "uni-id": uniID,
861 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700862 "meter-id": DsMeterID,
863 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000864 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700865 return 0, nil, nil
866 }
867 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700868 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700869 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700870 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700872 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000873
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 if tpInstanceExists {
875 return allocID, gemPortIDs, techProfileInstance
876 }
877
878 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700879 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000881 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700882 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700883 "intf-id": intfID,
884 "onu-id": onuID,
885 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700886 "alloc-ids": allocIDs,
887 "gemports": allgemPortIDs,
888 "device-id": f.deviceHandler.device.Id})
889 // Send Tconts and GEM ports to KV store
890 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530891 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400892 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700893 // CreateSchedulerQueues for EPON needs to be implemented here
894 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700895 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700896 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700897 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700898 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700899 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900
901 if tpInstanceExists {
902 return allocID, gemPortIDs, techProfileInstance
903 }
904
905 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700906 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000908 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909 log.Fields{
910 "alloc-ids": allocIDs,
911 "gemports": allgemPortIDs,
912 "device-id": f.deviceHandler.device.Id})
913 // Send Tconts and GEM ports to KV store
914 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
915 return allocID, gemPortIDs, techProfileInstance
916 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 log.Fields{
919 "tpInst": tpInst})
920 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530921 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530922}
923
npujarec5762e2020-01-01 14:08:48 +0530924func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530925
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530927 log.Fields{
928 "intf-id": intfID,
929 "onu-id": onuID,
930 "uni-id": uniID,
931 "alloc-id": allocID,
932 "gemport-ids": gemPortIDs,
933 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530934 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
npujarec5762e2020-01-01 14:08:48 +0530935 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, intfID, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000936 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 +0530937 }
npujarec5762e2020-01-01 14:08:48 +0530938 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, intfID, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000939 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 +0530940 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700941
Neha Sharma96b7bf22020-06-15 10:37:32 +0000942 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 -0400943 for _, gemPort := range gemPortIDs {
yasin sapli9e4c5092022-02-01 13:52:33 +0000944 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, intfID, onuID, gemPort); err != nil {
945 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
946 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400947 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530948}
949
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700950func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530951 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000952 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700953 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
954 var err error
955 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
956 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
957 if err != nil || f.techprofile == nil {
958 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
959 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
960 }
961 logger.Debugw(ctx, "init-tech-profile-done",
962 log.Fields{
963 "intf-id": intfID,
964 "device-id": f.deviceHandler.device.Id})
965 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700966 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530967 }
968 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700969 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
970 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 +0530971}
972
Gamze Abaka7650be62021-02-26 10:50:36 +0000973func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Andrea Campanellafaa42152021-10-28 11:50:56 +0530974 flowContext.classifier[PacketTagType] = SingleTag // FIXME: This hardcoding needs to be removed.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000975 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530976 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000977 "uplinkClassifier": flowContext.classifier,
978 "uplinkAction": flowContext.action})
979 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
Manikkaraj k884c1242019-04-11 16:26:42 +0530980 /* TODO: Install Secondary EAP on the subscriber vlan */
manikkaraj kbf256be2019-03-25 00:13:48 +0530981}
982
Gamze Abaka7650be62021-02-26 10:50:36 +0000983func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
984 downlinkClassifier := flowContext.classifier
985 downlinkAction := flowContext.action
986
Andrea Campanellafaa42152021-10-28 11:50:56 +0530987 // TODO: For now mark the PacketTagType as SingleTag when OLT is transparent to VLAN
988 // Per some deployment models, it is also possible that ONU operates on double tagged packets,
989 // so this hardcoding of SingeTag packet-tag-type may be problem for such deployment models.
990 // Need a better way for detection of packet tag type from OpenFlow message.
991 if _, ok := downlinkClassifier[VlanVid]; !ok {
992 downlinkClassifier[PacketTagType] = SingleTag
993 } else {
994 downlinkClassifier[PacketTagType] = DoubleTag
995 downlinkAction[PopVlan] = true
996 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000997 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530998 log.Fields{
999 "downlinkClassifier": downlinkClassifier,
1000 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001001 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1002 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1003 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001004 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001005 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001006 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301007 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001008 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301009 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001010 "onu-id": flowContext.onuID,
1011 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001012 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001013 }
1014 }
1015 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301016 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001017
Matt Jeannereted16b7c2019-11-01 13:31:35 -04001018 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1019 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
Girish Gowdra26f344b2019-10-23 14:39:13 +05301020 if ok {
1021 downlinkAction[VlanVid] = dlClVid & 0xfff
Girish Gowdra26f344b2019-10-23 14:39:13 +05301022 }
1023
Gamze Abaka7650be62021-02-26 10:50:36 +00001024 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301025}
1026
Gamze Abaka7650be62021-02-26 10:50:36 +00001027func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001028
Gamze Abaka7650be62021-02-26 10:50:36 +00001029 intfID := flowContext.intfID
1030 onuID := flowContext.onuID
1031 uniID := flowContext.uniID
1032 classifier := flowContext.classifier
1033 action := flowContext.action
1034 allocID := flowContext.allocID
1035 gemPortID := flowContext.gemPortID
1036 tpID := flowContext.tpID
1037 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001038 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301039 log.Fields{
1040 "intf-id": intfID,
1041 "onu-id": onuID,
1042 "uni-id": uniID,
1043 "device-id": f.deviceHandler.device.Id,
1044 "classifier": classifier,
1045 "action": action,
1046 "direction": direction,
1047 "alloc-id": allocID,
1048 "gemport-id": gemPortID,
1049 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001050
1051 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001052 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301053 log.Fields{
1054 "device-id": f.deviceHandler.device.Id,
1055 "intf-id": intfID,
1056 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001057 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301058 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001059 classifierProto, err := makeOpenOltClassifierField(classifier)
1060 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301061 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301062 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001063 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301064 log.Fields{
1065 "classifier": *classifierProto,
1066 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001067 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001068 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301069 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301070 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001071 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301072 log.Fields{
1073 "action": *actionProto,
1074 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001075 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301076 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301077 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001078 log.Fields{
1079 "classifier": classifier,
1080 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301081 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001082 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301083 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001084
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001085 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001086 OnuId: int32(onuID),
1087 UniId: int32(uniID),
1088 FlowId: logicalFlow.Id,
1089 FlowType: direction,
1090 AllocId: int32(allocID),
1091 NetworkIntfId: int32(networkIntfID),
1092 GemportId: int32(gemPortID),
1093 Classifier: classifierProto,
1094 Action: actionProto,
1095 Priority: int32(logicalFlow.Priority),
1096 Cookie: logicalFlow.Cookie,
1097 PortNo: flowContext.portNo,
1098 TechProfileId: tpID,
1099 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1100 PbitToGemport: flowContext.pbitToGem,
1101 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001102 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001103 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001104 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001106 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301107 log.Fields{"direction": direction,
1108 "device-id": f.deviceHandler.device.Id,
1109 "flow": flow,
1110 "intf-id": intfID,
1111 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001112
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301114}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001115
Gamze Abaka7650be62021-02-26 10:50:36 +00001116func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1117
1118 intfID := flowContext.intfID
1119 onuID := flowContext.onuID
1120 uniID := flowContext.uniID
1121 logicalFlow := flowContext.logicalFlow
1122 classifier := flowContext.classifier
1123 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301124
Neha Sharma96b7bf22020-06-15 10:37:32 +00001125 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301126 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301127 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301129 "action": action,
1130 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001131 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301132 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301133
1134 // Clear the action map
1135 for k := range action {
1136 delete(action, k)
1137 }
1138
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001139 action[TrapToHost] = true
1140 classifier[UDPSrc] = uint32(68)
1141 classifier[UDPDst] = uint32(67)
1142 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301143
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001144 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001145 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301146 log.Fields{
1147 "device-id": f.deviceHandler.device.Id,
1148 "intf-id": intfID,
1149 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001150 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301151 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301152
Neha Sharma96b7bf22020-06-15 10:37:32 +00001153 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301154 log.Fields{
1155 "ul_classifier": classifier,
1156 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001157 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301158 "intf-id": intfID,
1159 "onu-id": onuID,
1160 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301161
David K. Bainbridge794735f2020-02-11 21:01:37 -08001162 classifierProto, err := makeOpenOltClassifierField(classifier)
1163 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301164 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301165 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001166 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001167 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001168 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301169 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170 }
1171
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001173 OnuId: int32(onuID),
1174 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001176 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001177 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001178 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001179 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301180 Classifier: classifierProto,
1181 Action: actionProto,
1182 Priority: int32(logicalFlow.Priority),
1183 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001184 PortNo: flowContext.portNo,
1185 TechProfileId: flowContext.tpID,
1186 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1187 PbitToGemport: flowContext.pbitToGem,
1188 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001189 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001191 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001192 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001193 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301194 log.Fields{
1195 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001196 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301197 "intf-id": intfID,
1198 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199
David K. Bainbridge794735f2020-02-11 21:01:37 -08001200 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301201}
1202
Esin Karamanae41e2b2019-12-17 18:13:13 +00001203//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001204func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1205 delete(flowContext.classifier, VlanVid)
1206 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001207}
1208
1209//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001210func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1211
1212 intfID := flowContext.intfID
1213 onuID := flowContext.onuID
1214 uniID := flowContext.uniID
1215 logicalFlow := flowContext.logicalFlow
1216 classifier := flowContext.classifier
1217 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001218
Neha Sharma96b7bf22020-06-15 10:37:32 +00001219 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001220 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301221 return olterrors.NewErrNotFound("nni-interface-id",
1222 log.Fields{
1223 "classifier": classifier,
1224 "action": action,
1225 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001227 }
1228
1229 // Clear the action map
1230 for k := range action {
1231 delete(action, k)
1232 }
1233
1234 action[TrapToHost] = true
1235 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001237 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkIntfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001238 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001240 }
1241
Neha Sharma96b7bf22020-06-15 10:37:32 +00001242 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301243 log.Fields{
1244 "ul_classifier": classifier,
1245 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001246 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301247 "device-id": f.deviceHandler.device.Id,
1248 "intf-id": intfID,
1249 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001250
David K. Bainbridge794735f2020-02-11 21:01:37 -08001251 classifierProto, err := makeOpenOltClassifierField(classifier)
1252 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301253 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001255 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301256 log.Fields{
1257 "classifier": *classifierProto,
1258 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001259 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301261 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001262 }
1263
David K. Bainbridge794735f2020-02-11 21:01:37 -08001264 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001265 OnuId: int32(onuID),
1266 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001267 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001269 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001271 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001272 Classifier: classifierProto,
1273 Action: actionProto,
1274 Priority: int32(logicalFlow.Priority),
1275 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001276 PortNo: flowContext.portNo,
1277 TechProfileId: flowContext.tpID,
1278 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1279 PbitToGemport: flowContext.pbitToGem,
1280 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001281 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001284 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 -08001285 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288}
1289
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001290// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001291func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1292 intfID := flowContext.intfID
1293 onuID := flowContext.onuID
1294 uniID := flowContext.uniID
1295 portNo := flowContext.portNo
1296 allocID := flowContext.allocID
1297 gemPortID := flowContext.gemPortID
1298 logicalFlow := flowContext.logicalFlow
1299 classifier := flowContext.classifier
1300 action := flowContext.action
1301
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001302 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301303 log.Fields{
1304 "intf-id": intfID,
1305 "onu-id": onuID,
1306 "port-no": portNo,
1307 "alloc-id": allocID,
1308 "gemport-id": gemPortID,
1309 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001310 "flow": logicalFlow,
1311 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301312
1313 uplinkClassifier := make(map[string]interface{})
1314 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301315
manikkaraj kbf256be2019-03-25 00:13:48 +05301316 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001317 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001318 uplinkClassifier[PacketTagType] = SingleTag
1319 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001320 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301321 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001322 uplinkAction[TrapToHost] = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001323 if present := f.resourceMgr.IsFlowOnKvStore(ctx, intfID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001324 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301325 "device-id": f.deviceHandler.device.Id,
1326 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001327 "intf-id": intfID,
1328 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001329 return nil
Girish Gowdra3d633032019-12-10 16:37:05 +05301330 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001331 //Add Uplink EthType Flow
1332 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301333 log.Fields{
1334 "ul_classifier": uplinkClassifier,
1335 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001336 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301337 "device-id": f.deviceHandler.device.Id,
1338 "intf-id": intfID,
1339 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301340
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1342 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301343 return olterrors.NewErrInvalidValue(log.Fields{
1344 "classifier": uplinkClassifier,
1345 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301346 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001347 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301348 log.Fields{
1349 "classifier": *classifierProto,
1350 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001351 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001352 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301353 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301354 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001355 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301356 log.Fields{
1357 "action": *actionProto,
1358 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001359 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301360 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301361 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001362 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301363 "action": action,
1364 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001365 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301366 }
1367
David K. Bainbridge794735f2020-02-11 21:01:37 -08001368 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 OnuId: int32(onuID),
1370 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001371 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001372 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 AllocId: int32(allocID),
1374 NetworkIntfId: int32(networkIntfID),
1375 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301376 Classifier: classifierProto,
1377 Action: actionProto,
1378 Priority: int32(logicalFlow.Priority),
1379 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001380 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001381 TechProfileId: flowContext.tpID,
1382 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1383 PbitToGemport: flowContext.pbitToGem,
1384 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001385 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001386 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001387 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001388 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001389 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301390 log.Fields{
1391 "device-id": f.deviceHandler.device.Id,
1392 "onu-id": onuID,
1393 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001394 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301395 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001396
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301398}
1399
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001402
1403 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1404 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1405 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001406 if vlanID != ReservedVlan {
1407 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001408 classifier.OVid = vid
1409 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301411 // 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 -07001412 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1413 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301414 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1415 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1416 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1417 // becomes the IVid.
1418 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1419 if vid != ReservedVlan {
1420 classifier.IVid = vid
1421 }
1422 } else {
1423 if vid != ReservedVlan {
1424 classifier.OVid = vid
1425 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001426 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301427 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301428 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001429 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301430 classifier.OPbits = vlanPcp
1431 } else {
1432 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301433 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001434 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1435 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1436 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1437 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001438 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001439 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1440 classifier.PktTagType = pktTagType
1441
1442 switch pktTagType {
1443 case SingleTag:
1444 case DoubleTag:
1445 case Untagged:
1446 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001447 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301448 }
1449 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001450 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301451}
1452
Gamze Abaka724d0852020-03-18 12:10:24 +00001453func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001454 var actionCmd openoltpb2.ActionCmd
1455 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301456 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 if _, ok := actionInfo[PopVlan]; ok {
manikkaraj kbf256be2019-03-25 00:13:48 +05301458 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001459 if _, ok := actionInfo[VlanPcp]; ok {
1460 action.Cmd.RemarkInnerPbits = true
1461 action.IPbits = actionInfo[VlanPcp].(uint32)
1462 if _, ok := actionInfo[VlanVid]; ok {
1463 action.Cmd.TranslateInnerTag = true
1464 action.IVid = actionInfo[VlanVid].(uint32)
1465 }
1466 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001467 } else if _, ok := actionInfo[PushVlan]; ok {
1468 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301469 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001470 if _, ok := actionInfo[VlanPcp]; ok {
1471 action.OPbits = actionInfo[VlanPcp].(uint32)
1472 action.Cmd.RemarkOuterPbits = true
1473 if _, ok := classifierInfo[VlanVid]; ok {
1474 action.IVid = classifierInfo[VlanVid].(uint32)
1475 action.Cmd.TranslateInnerTag = true
1476 }
1477 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001478 } else if _, ok := actionInfo[TrapToHost]; ok {
1479 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
manikkaraj kbf256be2019-03-25 00:13:48 +05301480 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301481 // When OLT is transparent to vlans no-action is valid.
1482 /*
1483 else {
1484 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1485 }
1486 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001487 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301488}
1489
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001490// getTPpath return the ETCD path for a given UNI port
Neha Sharma96b7bf22020-06-15 10:37:32 +00001491func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, intfID uint32, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001492 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301493}
1494
Gamze Abakafee36392019-10-03 11:17:24 +00001495// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001496// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1497// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1498// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1499// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1500// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1501// because it was observed that if the ONU device was deleted too soon after the flows were
1502// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1503// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1504// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001505func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
npujarec5762e2020-01-01 14:08:48 +05301506 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, intfID, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001507 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1508
Gamze Abakafee36392019-10-03 11:17:24 +00001509 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001510
1511 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001512 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001513 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1514 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
1515 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1516 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1517 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1518 log.Fields{
1519 "tp-id": tpID,
1520 "path": tpPath})
1521 }
1522 switch tpInstance := tpInst.(type) {
1523 case *tp_pb.TechProfileInstance:
1524 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1525 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1526 }
1527 // Force cleanup scheduler/queues -- end
1528
1529 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301530 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001531 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301532 // return err
1533 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001534 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001535 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 +00001536 }
1537 return nil
1538}
1539
1540// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301541func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001542 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001543 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001544 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001545 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301546 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1547 log.Fields{
1548 "tp-id": tpID,
1549 "uni-port-name": uniPortName,
1550 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001551 }
1552 return nil
1553}
1554
David K. Bainbridge794735f2020-02-11 21:01:37 -08001555func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001556
1557 var intfID uint32
1558 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1559 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1560 */
1561 if deviceFlow.AccessIntfId != -1 {
1562 intfID = uint32(deviceFlow.AccessIntfId)
1563 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001564 // We need to log the valid interface ID.
1565 // 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 +00001566 intfID = uint32(deviceFlow.NetworkIntfId)
1567 }
1568
Neha Sharma96b7bf22020-06-15 10:37:32 +00001569 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301570 "flow": *deviceFlow,
1571 "device-id": f.deviceHandler.device.Id,
1572 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001573 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001574
1575 st, _ := status.FromError(err)
1576 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001577 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001578 "err": err,
1579 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301580 "device-id": f.deviceHandler.device.Id,
1581 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001582 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301583 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001584
1585 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001586 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301587 log.Fields{"err": err,
1588 "device-flow": deviceFlow,
1589 "device-id": f.deviceHandler.device.Id,
1590 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001591 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001592 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001593 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301594 log.Fields{
1595 "flow": *deviceFlow,
1596 "device-id": f.deviceHandler.device.Id,
1597 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001598
1599 // Case of trap-on-nni flow when deviceFlow.AccessIntfId is invalid (-1)
1600 if deviceFlow.AccessIntfId != -1 {
1601 // No need to register the flow if it is a trap on nni flow.
1602 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1603 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1604 return err
1605 }
1606 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001607 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001608}
1609
Neha Sharma96b7bf22020-06-15 10:37:32 +00001610func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1611 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301612 log.Fields{
1613 "flow": *deviceFlow,
1614 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001615 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001616 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001617 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001618 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301619 log.Fields{
1620 "err": err,
1621 "deviceFlow": deviceFlow,
1622 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001623 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001624 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001625 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001626 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001627
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001628 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001629 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001630 "of-flow-id": ofFlowID,
1631 "flow": *deviceFlow,
1632 "device-id": f.deviceHandler.device.Id,
1633 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001634 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301635}
1636
David K. Bainbridge794735f2020-02-11 21:01:37 -08001637func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001638
1639 classifierInfo := make(map[string]interface{})
1640 actionInfo := make(map[string]interface{})
1641
1642 classifierInfo[EthType] = uint32(LldpEthType)
1643 classifierInfo[PacketTagType] = Untagged
1644 actionInfo[TrapToHost] = true
1645
1646 // LLDP flow is installed to trap LLDP packets on the NNI port.
1647 // We manage flow_id resource pool on per PON port basis.
1648 // Since this situation is tricky, as a hack, we pass the NNI port
1649 // index (network_intf_id) as PON port Index for the flow_id resource
1650 // pool. Also, there is no ONU Id available for trapping LLDP packets
1651 // on NNI port, use onu_id as -1 (invalid)
1652 // ****************** CAVEAT *******************
1653 // This logic works if the NNI Port Id falls within the same valid
1654 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1655 // we need to have a re-look at this.
1656 // *********************************************
1657
1658 var onuID = -1
1659 var uniID = -1
1660 var gemPortID = -1
1661
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001662 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001663 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301664 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001666 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001667 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 return nil
Humera Kouser94d7a842019-08-25 19:04:32 -04001669 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001670
David K. Bainbridge794735f2020-02-11 21:01:37 -08001671 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1672 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301673 return olterrors.NewErrInvalidValue(
1674 log.Fields{
1675 "classifier": classifierInfo,
1676 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001677 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001678 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301679 log.Fields{
1680 "classifier": *classifierProto,
1681 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001682 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001683 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301684 return olterrors.NewErrInvalidValue(
1685 log.Fields{
1686 "action": actionInfo,
1687 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001688 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001689 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301690 log.Fields{
1691 "action": *actionProto,
1692 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001693
1694 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1695 OnuId: int32(onuID), // OnuId not required
1696 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001697 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001698 FlowType: Downstream,
1699 NetworkIntfId: int32(networkInterfaceID),
1700 GemportId: int32(gemPortID),
1701 Classifier: classifierProto,
1702 Action: actionProto,
1703 Priority: int32(flow.Priority),
1704 Cookie: flow.Cookie,
1705 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001707 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301708 log.Fields{
1709 "flow": downstreamflow,
1710 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001711 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001712 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301713 log.Fields{
1714 "device-id": f.deviceHandler.device.Id,
1715 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001716 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001717
David K. Bainbridge794735f2020-02-11 21:01:37 -08001718 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301719}
1720
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001721func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1722 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001723}
1724
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001725//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001726func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001727 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1728 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1729 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001730 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301731 log.Fields{
1732 "intf-id": intfID,
1733 "onu-id": onuID,
1734 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001736 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301737 return nil, olterrors.NewErrNotFound("onu-child-device",
1738 log.Fields{
1739 "onu-id": onuID,
1740 "intf-id": intfID,
1741 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001742 }
khenaidoo106c61a2021-08-11 18:05:46 -04001743 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 -07001744 //better to ad the device to cache here.
1745 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1746 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001747 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301748 log.Fields{
1749 "intf-id": intfID,
1750 "onu-id": onuID,
1751 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001752 }
1753
1754 return onuDev.(*OnuDevice), nil
1755}
1756
1757//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1759 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301760 log.Fields{
1761 "pon-port": intfID,
1762 "onu-id": onuID,
1763 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001764 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001766 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301767 return nil, olterrors.NewErrNotFound("onu",
1768 log.Fields{
1769 "interface-id": parentPortNo,
1770 "onu-id": onuID,
1771 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001772 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301773 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001774 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301775 log.Fields{
1776 "device-id": f.deviceHandler.device.Id,
1777 "child_device_id": onuDevice.Id,
1778 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301779 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301780}
1781
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1783 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301784 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001785 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301786 log.Fields{
1787 "intf-id": intfID,
1788 "onu-id": onuID,
1789 "uni-id": uniID,
1790 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001791 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301792 }
1793
khenaidoodc2116e2021-10-19 17:33:19 -04001794 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001795 DeviceId: onuDev.deviceID,
1796 UniId: uniID,
1797 TpInstancePath: tpPath,
1798 GemPortId: gemPortID,
1799 }
1800 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1801
1802 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301803 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1804 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001805 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1806 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301807 "onu-id": onuDev.deviceID,
1808 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001809 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301810 }
khenaidoo106c61a2021-08-11 18:05:46 -04001811
Neha Sharma96b7bf22020-06-15 10:37:32 +00001812 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301813 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001814 "msg": delGemPortMsg,
1815 "from-adapter": f.deviceHandler.device.Type,
1816 "to-adapter": onuDev.deviceType,
1817 "device-id": f.deviceHandler.device.Id,
1818 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301819 return nil
1820}
1821
Neha Sharma96b7bf22020-06-15 10:37:32 +00001822func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1823 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301824 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001825 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301826 log.Fields{
1827 "intf-id": intfID,
1828 "onu-id": onuID,
1829 "uni-id": uniID,
1830 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001831 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301832 }
1833
khenaidoodc2116e2021-10-19 17:33:19 -04001834 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001835 DeviceId: onuDev.deviceID,
1836 UniId: uniID,
1837 TpInstancePath: tpPath,
1838 AllocId: allocID,
1839 }
1840
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301842 log.Fields{
1843 "msg": *delTcontMsg,
1844 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001845
1846 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301847 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1848 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001849 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1850 "to-adapter": onuDev.adapterEndpoint,
1851 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301852 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001853 "device-id": f.deviceHandler.device.Id}, err)
1854
Girish Gowdra6b130582019-11-20 16:45:20 +05301855 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301857 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001858 "msg": delTcontMsg,
1859 "device-id": f.deviceHandler.device.Id,
1860 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301861 return nil
1862}
1863
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301864//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001865// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001866func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001867 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001868
1869 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001870
Girish Gowdraa482f272021-03-24 23:04:19 -07001871 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
1872 tpPath := f.getTPpath(ctx, intfID, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001873 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1874 log.Fields{
1875 "tpPath": tpPath,
1876 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001877
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001878 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001879 if err != nil || techprofileInst == nil {
1880 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1881 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1882 if childDevice == nil {
1883 // happens when subscriber un-provision is immediately followed by child device delete
1884 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1885 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1886 return nil
1887 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001888 return olterrors.NewErrNotFound("tech-profile-in-kv-store",
1889 log.Fields{
1890 "tp-id": tpID,
1891 "path": tpPath}, err)
1892 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001893
1894 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001895 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001896 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001897 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1898 gemPortID := gemPort.GemportId
yasin sapli9e4c5092022-02-01 13:52:33 +00001899 used := f.resourceMgr.IsGemPortUsedByAnotherFlow(gemPortID, flowID)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001900 if used {
yasin sapli9e4c5092022-02-01 13:52:33 +00001901 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, intfID, gemPortID)
1902 if err != nil {
1903 return err
1904 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001905 for i, flowIDinMap := range flowIDs {
1906 if flowIDinMap == flowID {
1907 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
Gamze Abaka745ccb72021-11-18 11:29:58 +00001908 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, intfID, gemPortID, flowIDs); err != nil {
1909 return err
1910 }
1911 break
1912 }
1913 }
1914 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1915 log.Fields{
1916 "gemport-id": gemPortID,
1917 "usedByFlows": flowIDs,
1918 "currentFlow": flowID,
1919 "device-id": f.deviceHandler.device.Id})
1920 allGemPortsFree = false
1921 }
1922 }
1923 if !allGemPortsFree {
1924 return nil
1925 }
1926 }
1927
1928 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 -08001929
1930 // 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 +00001931 switch techprofileInst := techprofileInst.(type) {
1932 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001933 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
1934 logger.Warn(ctx, err)
1935 }
1936 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
1937 logger.Warn(ctx, err)
1938 }
1939
1940 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1941 gemPortID := gemPort.GemportId
Girish Gowdraf3728b12022-02-02 21:46:51 -08001942 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, intfID, uint32(onuID), gemPortID) // ignore error and proceed.
1943
yasin sapli9e4c5092022-02-01 13:52:33 +00001944 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, intfID, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001945 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1946 log.Fields{
1947 "err": err,
1948 "intf": intfID,
1949 "onu-id": onuID,
1950 "uni-id": uniID,
1951 "device-id": f.deviceHandler.device.Id,
1952 "gemport-id": gemPortID})
1953 }
1954
1955 }
1956 // Remove queues at OLT in upstream and downstream direction
1957 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1958 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1959 logger.Warn(ctx, err)
1960 }
1961 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1962 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
1963 logger.Warn(ctx, err)
1964 }
1965 }
1966
1967 switch techprofileInst := techprofileInst.(type) {
1968 case *tp_pb.TechProfileInstance:
1969 // 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 +01001970 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
1971 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
1972 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001973 // all alloc object references removed, remove upstream scheduler
Andrea Campanella8a0d0502022-01-31 15:31:59 +01001974 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001975 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01001976 logger.Warn(ctx, err)
1977 }
1978 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08001979 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
1980 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
1981 } else {
1982 // just remove meter reference for the upstream direction for the current pon/onu/uni
1983 // 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
1984 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
1985 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01001986 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08001987 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
1988 // but still preserve it on the resource pool.
1989 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
1990 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01001991
Girish Gowdraf3728b12022-02-02 21:46:51 -08001992 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
1993 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
1994 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", intfID, uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
1995 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
1996 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001997 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001998 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001999 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa482f272021-03-24 23:04:19 -07002000 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002001 logger.Warn(ctx, err)
2002 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002003 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002004 logger.Warn(ctx, err)
2005 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002006 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002007 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002008 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302009 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002010 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302011 "onu-id": onuID,
2012 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002013 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002014 "alloc-id": techprofileInst.AllocId,
2015 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002016 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002017 f.resourceMgr.FreeAllocID(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002018 default:
2019 logger.Errorw(ctx, "error-unknown-tech",
2020 log.Fields{
2021 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002022 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002023
2024 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2025 switch techprofileInst := techprofileInst.(type) {
2026 case *tp_pb.TechProfileInstance:
2027 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2028 // Delete the gem port on the ONU.
2029 if sendDeleteGemRequest {
2030 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2031 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2032 log.Fields{
2033 "err": err,
2034 "intfID": intfID,
2035 "onu-id": onuID,
2036 "uni-id": uniID,
2037 "device-id": f.deviceHandler.device.Id,
2038 "gemport-id": gemPort.GemportId})
2039 }
2040 f.resourceMgr.FreeGemPortID(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId)
2041 }
2042 }
2043 }
2044
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302045 return nil
2046}
2047
David K. Bainbridge794735f2020-02-11 21:01:37 -08002048// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002049func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002050 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302051 log.Fields{
2052 "flowDirection": flowDirection,
2053 "flow": *flow,
2054 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002055
2056 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002057 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002058 }
2059
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302060 var ethType, ipProto, inPort uint32
2061 for _, field := range flows.GetOfbFields(flow) {
2062 if field.Type == flows.IP_PROTO {
2063 ipProto = field.GetIpProto()
2064 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2065 } else if field.Type == flows.ETH_TYPE {
2066 ethType = field.GetEthType()
2067 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2068 } else if field.Type == flows.IN_PORT {
2069 inPort = field.GetPort()
2070 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2071 }
2072 }
2073 portType := plt.IntfIDToPortTypeName(inPort)
2074 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2075 (portType == voltha.Port_ETHERNET_NNI) {
2076 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2077 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2078 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2079 // No more processing needed for trap from nni flows.
2080 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302081
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302082 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302083 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002084 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002085 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302086 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002087 onuID := int32(onu)
2088 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002089 tpID, err := getTpIDFromFlow(ctx, flow)
2090 if err != nil {
2091 return olterrors.NewErrNotFound("tp-id",
2092 log.Fields{
2093 "flow": flow,
2094 "intf-id": Intf,
2095 "onu-id": onuID,
2096 "uni-id": uniID,
2097 "device-id": f.deviceHandler.device.Id}, err)
2098 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099
Neha Sharma96b7bf22020-06-15 10:37:32 +00002100 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302101 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002102 "flow-id": flow.Id,
2103 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302104 "onu-id": onuID,
2105 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302106
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002107 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2108 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002109 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2110 return err
2111 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002112
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002113 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002114 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2115 "flow-id": flow.Id,
2116 "device-id": f.deviceHandler.device.Id,
2117 "onu-id": onuID,
2118 "intf": Intf,
2119 "err": err,
2120 })
2121 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302122 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002123
Girish Gowdra82c80982021-03-26 16:22:02 -07002124 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
2125 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, Intf, uint32(onuID), uint32(uniID), tpID, false); err != nil {
2126 return err
2127 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002128 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002129}
2130
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002131//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002132func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002133
Matteo Scandolof16389e2021-05-18 00:47:08 +00002134 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302135 var direction string
2136 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002137
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302138 for _, action := range flows.GetActions(flow) {
2139 if action.Type == flows.OUTPUT {
2140 if out := action.GetOutput(); out != nil {
2141 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002142 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302143 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002144 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002145 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002146 }
2147 }
2148 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002149
2150 if flows.HasGroup(flow) {
2151 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002152 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002153 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302154 direction = Upstream
2155 } else {
2156 direction = Downstream
2157 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302158
Girish Gowdracefae192020-03-19 18:14:10 -07002159 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002160 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002161
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002162 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002163}
2164
Esin Karamanae41e2b2019-12-17 18:13:13 +00002165//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2166func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002167 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002168 if ethType, ok := classifierInfo[EthType]; ok {
2169 if ethType.(uint32) == IPv4EthType {
2170 if ipProto, ok := classifierInfo[IPProto]; ok {
2171 if ipProto.(uint32) == IgmpProto {
2172 return true
2173 }
2174 }
2175 }
2176 }
2177 }
2178 return false
2179}
2180
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002181// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002182func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002183 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2184 // The device itself is going to be reset as part of deletion. So nothing to be done.
2185 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2186 return nil
2187 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002188 // Step1 : Fill flowControlBlock
2189 // Step2 : Push the flowControlBlock to ONU channel
2190 // Step3 : Wait on response channel for response
2191 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002192 startTime := time.Now()
2193 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002194 errChan := make(chan error)
2195 flowCb := flowControlBlock{
2196 ctx: ctx,
2197 addFlow: addFlow,
2198 flow: flow,
2199 flowMetadata: flowMetadata,
2200 errChan: &errChan,
2201 }
2202 inPort, outPort := getPorts(flow)
2203 var onuID uint32
2204 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002205 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002206 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002207 if f.flowHandlerRoutineActive[onuID] {
2208 // inPort or outPort is InvalidPort for trap-from-nni flows.
2209 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2210 // Send the flowCb on the ONU flow channel
2211 f.incomingFlows[onuID] <- flowCb
2212 // Wait on the channel for flow handlers return value
2213 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002214 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002215 return err
2216 }
2217 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2218 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002219}
2220
2221// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2222// 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 -07002223func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002224 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002225 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002226 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002227 // block on the channel to receive an incoming flow
2228 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002229 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002230 if flowCb.addFlow {
2231 logger.Info(flowCb.ctx, "adding-flow-start")
2232 startTime := time.Now()
2233 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2234 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2235 // Pass the return value over the return channel
2236 *flowCb.errChan <- err
2237 } else {
2238 logger.Info(flowCb.ctx, "removing-flow-start")
2239 startTime := time.Now()
2240 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2241 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2242 // Pass the return value over the return channel
2243 *flowCb.errChan <- err
2244 }
2245 case <-stopHandler:
2246 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2247 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002248 }
2249 }
2250}
2251
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002252// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002253func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002254 for i, v := range f.stopFlowHandlerRoutine {
2255 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002256 select {
2257 case v <- true:
2258 case <-time.After(time.Second * 5):
2259 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2260 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002261 }
2262 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002263 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002264 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2265}
2266
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002267// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302268// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002269func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002270 classifierInfo := make(map[string]interface{})
2271 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002272 var UsMeterID uint32
2273 var DsMeterID uint32
2274
Neha Sharma96b7bf22020-06-15 10:37:32 +00002275 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302276 log.Fields{
2277 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002278 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002279 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002280
Neha Sharma96b7bf22020-06-15 10:37:32 +00002281 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002282 if err != nil {
2283 // Error logging is already done in the called function
2284 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002285 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302286 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002287
Esin Karamanccb714b2019-11-29 15:02:06 +00002288 if flows.HasGroup(flow) {
2289 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002290 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002291 }
2292
manikkaraj k17652a72019-05-06 09:06:36 -04002293 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002294 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002295 if err != nil {
2296 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002297 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002298 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002299
Neha Sharma96b7bf22020-06-15 10:37:32 +00002300 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302301 log.Fields{
2302 "classifierinfo_inport": classifierInfo[InPort],
2303 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002304 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002305
Humera Kouser94d7a842019-08-25 19:04:32 -04002306 if ethType, ok := classifierInfo[EthType]; ok {
2307 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002308 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002309 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002310 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002311 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002312 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002313 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2314 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2315 }
2316 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002317 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002318 if ipProto, ok := classifierInfo[IPProto]; ok {
2319 if ipProto.(uint32) == IPProtoDhcp {
2320 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302321 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002322 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002323 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002324 }
2325 }
2326 }
2327 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002328 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002330 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002331 }
A R Karthick1f85b802019-10-11 05:06:05 +00002332
npujarec5762e2020-01-01 14:08:48 +05302333 f.resourceMgr.AddUniPortToOnuInfo(ctx, intfID, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002334
Girish Gowdra6071f382021-12-14 12:52:04 +05302335 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002336 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302337 return olterrors.NewErrNotFound("tpid-for-flow",
2338 log.Fields{
2339 "flow": flow,
2340 "intf-id": IntfID,
2341 "onu-id": onuID,
2342 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002343 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002344 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302345 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302346 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302347 "intf-id": intfID,
2348 "onu-id": onuID,
2349 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002350 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002351 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002352 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302353 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2354 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2355 return err
2356 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002357 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002358 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002359 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302360 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2361 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2362 return err
2363 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002364 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302365 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002366}
Girish Gowdra3d633032019-12-10 16:37:05 +05302367
Esin Karamanccb714b2019-11-29 15:02:06 +00002368// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002369func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302370 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002371 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302372 "classifier-info": classifierInfo,
2373 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002374
Esin Karaman65409d82020-03-18 10:58:18 +00002375 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002376 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002377 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002378 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002379
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002380 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002381
David K. Bainbridge794735f2020-02-11 21:01:37 -08002382 onuID := NoneOnuID
2383 uniID := NoneUniID
Esin Karamanccb714b2019-11-29 15:02:06 +00002384
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002385 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), flow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002386 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002387 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002388 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002389 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2390 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002391 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002392 }
2393 groupID := actionInfo[GroupID].(uint32)
2394 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002395 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002396 FlowType: Multicast,
2397 NetworkIntfId: int32(networkInterfaceID),
2398 GroupId: groupID,
2399 Classifier: classifierProto,
2400 Priority: int32(flow.Priority),
2401 Cookie: flow.Cookie}
2402
Kent Hagermane6ff1012020-07-14 15:07:53 -04002403 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002404 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002405 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002406 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002407 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002408 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002409 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002410 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002411 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002412 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002413 //cached group can be removed now
2414 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002415 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002416 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002417 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002418
David K. Bainbridge794735f2020-02-11 21:01:37 -08002419 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002420}
2421
Esin Karaman65409d82020-03-18 10:58:18 +00002422//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2423func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2424 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002425 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002426 if err != nil {
2427 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2428 }
2429 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002430 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002431
2432 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2433 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002434}
2435
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002436//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002437func (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 -07002438
Neha Sharma96b7bf22020-06-15 10:37:32 +00002439 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302440 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002441 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302442 log.Fields{
2443 "intf-id": intfID,
2444 "onu-id": onuID,
2445 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002446 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302447 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002448 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002449
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 tpPath := f.getTPpath(ctx, intfID, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002451 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002452 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002453 UniId: uniID,
2454 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002455 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002456 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002458
2459 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2460 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302461 return olterrors.NewErrCommunication("send-techprofile-download-request",
2462 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002463 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302464 "to-adapter": onuDev.deviceType,
2465 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002466 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002467 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002468 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302469 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302470}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002471
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002472//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302473func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002474 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002475
2476 if packetIn.IntfType == "pon" {
2477 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002478 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002479 onuID, uniID := packetIn.OnuId, packetIn.UniId
2480 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 +00002481
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002482 if packetIn.PortNo != 0 {
2483 logicalPortNum = packetIn.PortNo
2484 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002485 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002486 }
2487 // 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 +00002488 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002489 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002490 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002491 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002492
2493 if logger.V(log.DebugLevel) {
2494 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2495 log.Fields{
2496 "logical-port-num": logicalPortNum,
2497 "intf-type": packetIn.IntfType,
2498 "packet": hex.EncodeToString(packetIn.Pkt),
2499 })
2500 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002501 return logicalPortNum, nil
2502}
2503
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002504//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002505func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002506 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002507
2508 ctag, priority, err := getCTagFromPacket(ctx, packet)
2509 if err != nil {
2510 return 0, err
2511 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302512
Esin Karaman7fb80c22020-07-16 14:23:33 +00002513 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002514 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002515 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002516 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002517 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302518 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002519 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302520 log.Fields{
2521 "pktinkey": pktInkey,
2522 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002523
2524 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002525 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302526 //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 +00002527 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302528 if err == nil {
2529 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002530 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302531 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002532 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002533 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302534 log.Fields{
2535 "pktinkey": pktInkey,
2536 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302537 return gemPortID, nil
2538 }
2539 }
Shrey Baid26912972020-04-16 21:02:31 +05302540 return uint32(0), olterrors.NewErrNotFound("gem-port",
2541 log.Fields{
2542 "pktinkey": pktInkey,
2543 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002544
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545}
2546
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002547func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2548 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002549 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002550 classifier[PacketTagType] = DoubleTag
2551 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002552 /* We manage flowId resource pool on per PON port basis.
2553 Since this situation is tricky, as a hack, we pass the NNI port
2554 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002555 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002556 on NNI port, use onu_id as -1 (invalid)
2557 ****************** CAVEAT *******************
2558 This logic works if the NNI Port Id falls within the same valid
2559 range of PON Port Ids. If this doesn't work for some OLT Vendor
2560 we need to have a re-look at this.
2561 *********************************************
2562 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002563 onuID := -1
2564 uniID := -1
2565 gemPortID := -1
2566 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002567 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302568 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302569 return olterrors.NewErrNotFound("nni-intreface-id",
2570 log.Fields{
2571 "classifier": classifier,
2572 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002573 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302574 }
2575
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002576 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002577 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002578 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002579 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002580
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002581 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2582 log.Fields{
2583 "classifier": classifier,
2584 "action": action,
2585 "flowId": logicalFlow.Id,
2586 "intf-id": networkInterfaceID})
2587
David K. Bainbridge794735f2020-02-11 21:01:37 -08002588 classifierProto, err := makeOpenOltClassifierField(classifier)
2589 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002590 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002591 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002592 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002593 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002594 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002595 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002596 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002597 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002598 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2599 OnuId: int32(onuID), // OnuId not required
2600 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002601 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002602 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002603 AllocId: int32(allocID), // AllocId not used
2604 NetworkIntfId: int32(networkInterfaceID),
2605 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002606 Classifier: classifierProto,
2607 Action: actionProto,
2608 Priority: int32(logicalFlow.Priority),
2609 Cookie: logicalFlow.Cookie,
2610 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002611 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002612 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002613 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002614 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002615 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002616}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002617
Esin Karamanae41e2b2019-12-17 18:13:13 +00002618//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2619func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2620 var packetType string
2621 ovid, ivid := false, false
2622 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2623 vid := vlanID & VlanvIDMask
2624 if vid != ReservedVlan {
2625 ovid = true
2626 }
2627 }
2628 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2629 vid := uint32(metadata)
2630 if vid != ReservedVlan {
2631 ivid = true
2632 }
2633 }
2634 if ovid && ivid {
2635 packetType = DoubleTag
2636 } else if !ovid && !ivid {
2637 packetType = Untagged
2638 } else {
2639 packetType = SingleTag
2640 }
2641 return packetType
2642}
2643
2644//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002645func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002646 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002647 action := make(map[string]interface{})
2648 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2649 action[TrapToHost] = true
2650 /* We manage flowId resource pool on per PON port basis.
2651 Since this situation is tricky, as a hack, we pass the NNI port
2652 index (network_intf_id) as PON port Index for the flowId resource
2653 pool. Also, there is no ONU Id available for trapping packets
2654 on NNI port, use onu_id as -1 (invalid)
2655 ****************** CAVEAT *******************
2656 This logic works if the NNI Port Id falls within the same valid
2657 range of PON Port Ids. If this doesn't work for some OLT Vendor
2658 we need to have a re-look at this.
2659 *********************************************
2660 */
2661 onuID := -1
2662 uniID := -1
2663 gemPortID := -1
2664 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002665 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002666 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302667 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 "classifier": classifier,
2669 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002670 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002671 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002672 if present := f.resourceMgr.IsFlowOnKvStore(ctx, networkInterfaceID, int32(onuID), int32(uniID), logicalFlow.Id); present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002673 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002674 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002675 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002676
David K. Bainbridge794735f2020-02-11 21:01:37 -08002677 classifierProto, err := makeOpenOltClassifierField(classifier)
2678 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002679 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002680 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002681 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002682 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002683 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002684 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002685 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002687 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2688 OnuId: int32(onuID), // OnuId not required
2689 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002690 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002691 FlowType: Downstream,
2692 AllocId: int32(allocID), // AllocId not used
2693 NetworkIntfId: int32(networkInterfaceID),
2694 GemportId: int32(gemPortID), // GemportId not used
2695 Classifier: classifierProto,
2696 Action: actionProto,
2697 Priority: int32(logicalFlow.Priority),
2698 Cookie: logicalFlow.Cookie,
2699 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002700 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002701 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002703 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002704
David K. Bainbridge794735f2020-02-11 21:01:37 -08002705 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002706}
2707
salmansiddiqui7ac62132019-08-22 03:58:50 +00002708func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2709 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302710 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002711 }
2712 if Dir == tp_pb.Direction_UPSTREAM {
2713 return "upstream", nil
2714 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2715 return "downstream", nil
2716 }
2717 return "", nil
2718}
2719
Kent Hagermane6ff1012020-07-14 15:07:53 -04002720// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302721func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002722 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002723 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002724 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002725 intfID := args[IntfID]
2726 onuID := args[OnuID]
2727 uniID := args[UniID]
2728 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002729 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002730 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002731 gemToAes := make(map[uint32]bool)
2732
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002733 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002734 var direction = tp_pb.Direction_UPSTREAM
2735 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002736 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002737 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002738 attributes = TpInst.UpstreamGemPortAttributeList
2739 } else {
2740 attributes = TpInst.DownstreamGemPortAttributeList
2741 direction = tp_pb.Direction_DOWNSTREAM
2742 }
2743 default:
2744 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002745 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002746 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002747
2748 if len(gemPorts) == 1 {
2749 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002750 gemPortID = gemPorts[0]
2751 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002752 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2753 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002754 pBitMap := attributes[idx].PbitMap
2755 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2756 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2757 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002758 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002759 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2760 if pbitSet == pbit1 {
2761 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2762 pbitToGem[pcp] = gemID
2763 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002764 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002765 }
2766 }
2767 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002768 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2769 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2770 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002771 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002772 }
2773
Gamze Abaka7650be62021-02-26 10:50:36 +00002774 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2775 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2776
salmansiddiqui7ac62132019-08-22 03:58:50 +00002777 if ipProto, ok := classifierInfo[IPProto]; ok {
2778 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002779 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002780 "tp-id": tpID,
2781 "alloc-id": allocID,
2782 "intf-id": intfID,
2783 "onu-id": onuID,
2784 "uni-id": uniID,
2785 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002786 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002787 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002788 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002789 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})
2790 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002791 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002792 }
2793
Girish Gowdra32625212020-04-29 11:26:35 -07002794 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002795 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302796 log.Fields{
2797 "intf-id": intfID,
2798 "onu-id": onuID,
2799 "uni-id": uniID,
2800 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002801 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002802 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002803 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})
2804 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002805 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002807 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002808 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002809 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002810 }
2811 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002812 if ethType.(uint32) == EapEthType {
2813 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002814 "intf-id": intfID,
2815 "onu-id": onuID,
2816 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002817 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002818 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002819 var vlanID uint32
2820 if val, ok := classifierInfo[VlanVid]; ok {
2821 vlanID = (val.(uint32)) & VlanvIDMask
2822 } else {
2823 vlanID = DefaultMgmtVlan
2824 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002825 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002826 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002827 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})
2828 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002829 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002830 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002831 } else if ethType.(uint32) == PPPoEDEthType {
2832 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2833 "tp-id": tpID,
2834 "alloc-id": allocID,
2835 "intf-id": intfID,
2836 "onu-id": onuID,
2837 "uni-id": uniID,
2838 })
2839 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002840 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002841 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002842 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})
2843 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002844 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002845 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002846 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002847 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002848 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002849 "intf-id": intfID,
2850 "onu-id": onuID,
2851 "uni-id": uniID,
2852 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002853 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002854 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002855 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002856 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})
2857 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002858 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002859 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002860 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002862 "intf-id": intfID,
2863 "onu-id": onuID,
2864 "uni-id": uniID,
2865 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002866 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002867 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002869 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})
2870 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002871 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002872 }
2873 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002874 return olterrors.NewErrInvalidValue(log.Fields{
2875 "intf-id": intfID,
2876 "onu-id": onuID,
2877 "uni-id": uniID,
2878 "classifier": classifierInfo,
2879 "action": actionInfo,
2880 "flow": flow},
2881 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002882 }
2883 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002884 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002885 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002886 logger.Warn(ctx, err)
2887 }
2888 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002889 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002890}
2891
Gamze Abakacb0e6772021-06-10 08:32:12 +00002892func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002893 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2894 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2895 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 +05302896 for i := 0; i < len(tpInstances); i++ {
2897 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002898 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002899 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002900 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002901 log.Fields{
2902 "device-id": f.deviceHandler.device.Id,
2903 "intfID": sq.intfID,
2904 "onuID": sq.onuID,
2905 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002906 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002907 })
2908 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302909 }
2910 }
2911 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002912 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002913}
2914
Neha Sharma96b7bf22020-06-15 10:37:32 +00002915func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002916 for _, field := range flows.GetOfbFields(flow) {
2917 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002918 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002919 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002920 } else if field.Type == flows.ETH_DST {
2921 classifierInfo[EthDst] = field.GetEthDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002922 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07002923 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002924 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002925 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002926 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002927 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002928 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002929 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05302930 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
2931 if field.GetVlanVid() != ReservedVlan {
2932 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
2933 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
2934 }
Scott Baker355d1742019-10-24 10:57:52 -07002935 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002936 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002937 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002938 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002939 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002940 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002941 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002944 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002945 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002946 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002947 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002948 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002949 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002950 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002951 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002952 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07002953 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002954 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002955 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002956 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002958 return
2959 }
2960 }
2961}
2962
Neha Sharma96b7bf22020-06-15 10:37:32 +00002963func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07002964 for _, action := range flows.GetActions(flow) {
2965 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002966 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07002967 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002968 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00002970 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 }
Scott Baker355d1742019-10-24 10:57:52 -07002972 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002973 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00002974 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07002975 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002976 if out := action.GetPush(); out != nil {
2977 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002978 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002979 } else {
2980 actionInfo[PushVlan] = true
2981 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00002982 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05302983 log.Fields{
2984 "push-tpid": actionInfo[TPID].(uint32),
2985 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00002986 }
2987 }
Scott Baker355d1742019-10-24 10:57:52 -07002988 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002989 if out := action.GetSetField(); out != nil {
2990 if field := out.GetField(); field != nil {
2991 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00002992 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002993 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
2995 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002996 }
2997 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002998 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002999 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003001 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003002 }
3003 }
3004 return nil
3005}
3006
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003008 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003009 fieldtype := ofbField.GetType()
3010 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003011 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3012 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003014 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003015 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003016 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003017 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3018 pcp := ofbField.GetVlanPcp()
3019 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003020 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003021 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003023 }
3024 }
3025}
3026
Neha Sharma96b7bf22020-06-15 10:37:32 +00003027func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003028 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003029 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003030 } else {
3031 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003032 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003033 }
3034}
3035
Neha Sharma96b7bf22020-06-15 10:37:32 +00003036func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003037 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003038 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003040 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003041 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003043 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303044 log.Fields{
3045 "newinport": classifierInfo[InPort].(uint32),
3046 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303048 return olterrors.NewErrNotFound("child-in-port",
3049 log.Fields{
3050 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3051 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003052 }
3053 }
3054 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003055 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003057 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003058 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003059 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303061 log.Fields{
3062 "newoutport": actionInfo[Output].(uint32),
3063 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303065 return olterrors.NewErrNotFound("out-port",
3066 log.Fields{
3067 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3068 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 }
3070 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003071 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003072 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003073 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003074 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303075 log.Fields{
3076 "newinport": actionInfo[Output].(uint32),
3077 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303079 return olterrors.NewErrNotFound("nni-port",
3080 log.Fields{
3081 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3082 "in-port": classifierInfo[InPort].(uint32),
3083 "out-port": actionInfo[Output].(uint32),
3084 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 }
3086 }
3087 }
3088 return nil
3089}
Gamze Abakafee36392019-10-03 11:17:24 +00003090
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003092 /* Metadata 8 bytes:
3093 Most Significant 2 Bytes = Inner VLAN
3094 Next 2 Bytes = Tech Profile ID(TPID)
3095 Least Significant 4 Bytes = Port ID
3096 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3097 subscriber related flows.
3098 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003100 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003101 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003102 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003104 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003105}
3106
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003107func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003108 for _, sliceElement := range slice {
3109 if sliceElement == item {
3110 return slice
3111 }
3112 }
3113 return append(slice, item)
3114}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303115
3116// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303118
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003119 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303120 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003121 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003122 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003123 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003124 log.Fields{
3125 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003126 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003127 return uint32(0), err
3128 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003129 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303130 return intfID, nil
3131 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003132 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003133 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003134 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003135 log.Fields{
3136 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003137 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003138 return uint32(0), err
3139 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303141 return intfID, nil
3142 }
3143 return uint32(0), nil
3144}
3145
3146// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003147func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3148 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3149 if err != nil {
3150 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3151 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3152 return
3153 }
3154 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003155
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003156 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003157 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003158 f.packetInGemPortLock.RUnlock()
3159
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303160 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003161 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162 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 +05303163 log.Fields{
3164 "pktinkey": pktInkey,
3165 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003166 return
3167 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303168 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003169 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003170 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003171 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003172
npujarec5762e2020-01-01 14:08:48 +05303173 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003174 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 +05303175 log.Fields{
3176 "pktinkey": pktInkey,
3177 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303178}
3179
Esin Karaman7fb80c22020-07-16 14:23:33 +00003180//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3181func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3182 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003183 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003184 return 0, 0, errors.New("invalid packet length")
3185 }
3186 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3187 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3188
3189 var index int8
3190 if outerEthType == 0x8100 {
3191 if innerEthType == 0x8100 {
3192 // q-in-q 802.1ad or 802.1q double tagged packet.
3193 // get the inner vlanId
3194 index = 18
3195 } else {
3196 index = 14
3197 }
3198 priority := (packet[index] >> 5) & 0x7
3199 //13 bits composes vlanId value
3200 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3201 return vlan, priority, nil
3202 }
3203 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3204 return 0, 0, nil
3205}
3206
Girish Gowdra9602eb42020-09-09 15:50:39 -07003207//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3208// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003209func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003210 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003211 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3212 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003213 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003214 "flow-id": flow.Id,
3215 "device-id": f.deviceHandler.device.Id})
3216 // Remove from device
3217 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3218 // DKB
3219 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3220 log.Fields{
3221 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003222 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003223 return err
3224 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003225
3226 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003227}
3228
khenaidoodc2116e2021-10-19 17:33:19 -04003229func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003230 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003231 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003232 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003233 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003234 }
3235
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003236 switch tpInst := tpInst.(type) {
3237 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003238 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003239 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003240 DeviceId: onuDeviceID,
3241 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003242 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003243 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003244 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003245 case *tp_pb.EponTechProfileInstance:
3246 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003247 DeviceId: onuDeviceID,
3248 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003249 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003250 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003251 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003252 default:
3253 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003254 }
khenaidoodc2116e2021-10-19 17:33:19 -04003255 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003256 DeviceId: onuDeviceID,
3257 UniId: uniID,
3258 TpInstancePath: tpPath,
3259 TechTpInstance: nil,
3260 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003261}
3262
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003263// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3264func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3265
3266 intfID := sq.intfID
3267 onuID := sq.onuID
3268 uniID := sq.uniID
3269 tpID := sq.tpID
3270
3271 var reverseDirection string
3272 if sq.direction == tp_pb.Direction_UPSTREAM {
3273 reverseDirection = "downstream"
3274 } else {
3275 reverseDirection = "upstream"
3276 }
3277
3278 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
3279 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, intfID, onuID, uniID, tpID); KvStoreMeter != nil {
3280 return
3281 }
3282
3283 // revert-delete tech-profile instance and delete tech profile id for onu
3284 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})
3285 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3286 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
3287 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, intfID, onuID, uniID, tpID)
3288
3289 // free gem/alloc
3290 switch techprofileInst := sq.tpInst.(type) {
3291 case *tp_pb.TechProfileInstance:
3292 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
3293 f.resourceMgr.FreeGemPortID(ctx, intfID, onuID, uniID, gem.GemportId)
3294 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08003295 f.resourceMgr.FreeAllocID(ctx, intfID, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003296 }
3297}
3298
3299// revertSchduler is called when CreateQueues request fails
3300func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3301 // revert scheduler
3302 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})
3303 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3304 IntfId: sq.intfID, OnuId: sq.onuID,
3305 UniId: sq.uniID, PortNo: sq.uniPort,
3306 TrafficScheds: TrafficSched})
3307}
Girish Gowdra6071f382021-12-14 12:52:04 +05303308
3309// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3310func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
3311 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID)
3312 if err != nil {
3313 return olterrors.NewErrNotFound("meter",
3314 log.Fields{"intf-id": intfID,
3315 "onu-id": onuID,
3316 "uni-id": uniID,
3317 "device-id": f.deviceHandler.device.Id}, err)
3318 }
3319
3320 if meterInfo != nil {
3321 // If RefCnt become 0 clear the meter information from the DB.
3322 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
3323 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, intfID, onuID, uniID, tpID); err != nil {
3324 return err
3325 }
3326 } else if meterInfo.MeterID != meterID {
3327 logger.Errorw(ctx, "meter-mismatch-for-direction",
3328 log.Fields{"direction": direction,
3329 "kv-store-meter-id": meterInfo.MeterID,
3330 "meter-id-in-flow": meterID,
3331 "device-id": f.deviceHandler.device.Id})
3332 return olterrors.NewErrInvalidValue(log.Fields{
3333 "unsupported": "meter-id",
3334 "kv-store-meter-id": meterInfo.MeterID,
3335 "meter-id-in-flow": meterID,
3336 "device-id": f.deviceHandler.device.Id}, nil)
3337 }
3338 }
3339 return nil
3340}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003341
3342func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3343 /* After we successfully remove the scheduler configuration on the OLT device,
3344 * delete the meter id on the KV store.
3345 */
3346 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.intfID, sq.onuID, sq.uniID, sq.tpID)
3347 if err != nil {
3348 return olterrors.NewErrAdapter("unable-to-remove-meter",
3349 log.Fields{
3350 "onu": sq.onuID,
3351 "device-id": f.deviceHandler.device.Id,
3352 "intf-id": sq.intfID,
3353 "onu-id": sq.onuID,
3354 "uni-id": sq.uniID,
3355 "uni-port": sq.uniPort}, err)
3356 }
3357 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3358 log.Fields{
3359 "dir": direction,
3360 "device-id": f.deviceHandler.device.Id,
3361 "intf-id": sq.intfID,
3362 "onu-id": sq.onuID,
3363 "uni-id": sq.uniID,
3364 "uni-port": sq.uniPort})
3365 return err
3366}