blob: 6cc4f5bb5fc46239d17a939571757dce12e833e3 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
2 * Copyright 2018-present Open Networking Foundation
3
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7
8 * http://www.apache.org/licenses/LICENSE-2.0
9
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Scott Bakerdbd960e2020-02-28 08:57:51 -080017//Package core provides the utility for olt devices, flows and statistics
18package core
manikkaraj kbf256be2019-03-25 00:13:48 +053019
20import (
21 "context"
Matteo Scandolo6056e822019-11-13 14:05:29 -080022 "encoding/hex"
Girish Gowdracefae192020-03-19 18:14:10 -070023 "errors"
manikkaraj kbf256be2019-03-25 00:13:48 +053024 "fmt"
Gamze Abaka7650be62021-02-26 10:50:36 +000025 "strconv"
serkant.uluderya4aff1862020-09-17 23:35:26 +030026 "strings"
27 "sync"
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -070028 "time"
serkant.uluderya4aff1862020-09-17 23:35:26 +030029
khenaidoo106c61a2021-08-11 18:05:46 -040030 "github.com/opencord/voltha-lib-go/v7/pkg/meters"
Mahir Gunyel199570a2021-07-04 15:39:36 -070031
khenaidoo106c61a2021-08-11 18:05:46 -040032 "github.com/opencord/voltha-lib-go/v7/pkg/flows"
33 "github.com/opencord/voltha-lib-go/v7/pkg/log"
Mahir Gunyel85f61c12021-10-06 11:53:45 -070034 plt "github.com/opencord/voltha-lib-go/v7/pkg/platform"
khenaidoo106c61a2021-08-11 18:05:46 -040035 tp "github.com/opencord/voltha-lib-go/v7/pkg/techprofile"
Scott Bakerdbd960e2020-02-28 08:57:51 -080036 rsrcMgr "github.com/opencord/voltha-openolt-adapter/internal/pkg/resourcemanager"
khenaidoo106c61a2021-08-11 18:05:46 -040037 "github.com/opencord/voltha-protos/v5/go/common"
khenaidoodc2116e2021-10-19 17:33:19 -040038 ia "github.com/opencord/voltha-protos/v5/go/inter_adapter"
khenaidoo106c61a2021-08-11 18:05:46 -040039 ofp "github.com/opencord/voltha-protos/v5/go/openflow_13"
40 openoltpb2 "github.com/opencord/voltha-protos/v5/go/openolt"
41 tp_pb "github.com/opencord/voltha-protos/v5/go/tech_profile"
42 "github.com/opencord/voltha-protos/v5/go/voltha"
Chaitrashree G S579fe732019-08-20 20:50:47 -040043
Thomas Lee S94109f12020-03-03 16:39:29 +053044 "github.com/opencord/voltha-openolt-adapter/internal/pkg/olterrors"
Daniele Rossi22db98e2019-07-11 11:50:00 +000045 "google.golang.org/grpc/codes"
46 "google.golang.org/grpc/status"
manikkaraj kbf256be2019-03-25 00:13:48 +053047)
48
49const (
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070050 //IPProtoDhcp flow category
51 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Girish Gowdraa09aeab2020-09-14 16:30:52 -070053 //IgmpProto proto value
54 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
56 //EapEthType eapethtype value
57 EapEthType = 0x888e
58 //LldpEthType lldp ethtype value
59 LldpEthType = 0x88cc
Esin Karamanae41e2b2019-12-17 18:13:13 +000060 //IPv4EthType IPv4 ethernet type value
61 IPv4EthType = 0x800
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030062 //PPPoEDEthType PPPoE discovery ethernet type value
63 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Andrea Campanella7acc0b92020-02-14 09:20:49 +010065 //ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
66 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070068 //DefaultMgmtVlan default vlan value
69 DefaultMgmtVlan = 4091
manikkaraj kbf256be2019-03-25 00:13:48 +053070
manikkaraj kbf256be2019-03-25 00:13:48 +053071 // Openolt Flow
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070072
David K. Bainbridge82efc492019-09-04 09:57:11 -070073 //Upstream constant
74 Upstream = "upstream"
75 //Downstream constant
76 Downstream = "downstream"
Esin Karamanccb714b2019-11-29 15:02:06 +000077 //Multicast constant
78 Multicast = "multicast"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070079 //PacketTagType constant
80 PacketTagType = "pkt_tag_type"
David K. Bainbridge82efc492019-09-04 09:57:11 -070081 //Untagged constant
82 Untagged = "untagged"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070083 //SingleTag constant
84 SingleTag = "single_tag"
85 //DoubleTag constant
86 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
90 //EthType constant
91 EthType = "eth_type"
Esin Karamanccb714b2019-11-29 15:02:06 +000092 //EthDst constant
93 EthDst = "eth_dst"
Girish Gowdraffa52e52022-02-16 15:48:10 -080094 //EthSrc constant
95 EthSrc = "eth_src"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070096 //TPID constant
97 TPID = "tpid"
98 //IPProto constant
99 IPProto = "ip_proto"
100 //InPort constant
101 InPort = "in_port"
102 //VlanVid constant
103 VlanVid = "vlan_vid"
104 //VlanPcp constant
105 VlanPcp = "vlan_pcp"
106
107 //UDPDst constant
108 UDPDst = "udp_dst"
109 //UDPSrc constant
110 UDPSrc = "udp_src"
111 //Ipv4Dst constant
112 Ipv4Dst = "ipv4_dst"
113 //Ipv4Src constant
114 Ipv4Src = "ipv4_src"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700115 //Metadata constant
116 Metadata = "metadata"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700117 //TunnelID constant
118 TunnelID = "tunnel_id"
David K. Bainbridge82efc492019-09-04 09:57:11 -0700119 //Output constant
120 Output = "output"
Esin Karamanccb714b2019-11-29 15:02:06 +0000121 //GroupID constant
122 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
125 //PopVlan constant
126 PopVlan = "pop_vlan"
127 //PushVlan constant
128 PushVlan = "push_vlan"
129 //TrapToHost constant
130 TrapToHost = "trap_to_host"
Manikkaraj kb1d51442019-07-23 10:41:02 -0400131 //MaxMeterBand constant
132 MaxMeterBand = 2
133 //VlanPCPMask contant
134 VlanPCPMask = 0xFF
135 //VlanvIDMask constant
136 VlanvIDMask = 0xFFF
Gamze Abakafee36392019-10-03 11:17:24 +0000137 //IntfID constant
138 IntfID = "intfId"
139 //OnuID constant
140 OnuID = "onuId"
141 //UniID constant
142 UniID = "uniId"
143 //PortNo constant
144 PortNo = "portNo"
145 //AllocID constant
146 AllocID = "allocId"
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000147 //GemID constant
148 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000149
150 //NoneOnuID constant
151 NoneOnuID = -1
152 //NoneUniID constant
153 NoneUniID = -1
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700154
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700155 // Max number of flows that can be queued per ONU
156 maxConcurrentFlowsPerOnu = 20
manikkaraj kbf256be2019-03-25 00:13:48 +0530157
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700158 bitMapPrefix = "0b"
159 pbit1 = '1'
160)
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400161
Gamze Abakafee36392019-10-03 11:17:24 +0000162type schedQueue struct {
163 direction tp_pb.Direction
164 intfID uint32
165 onuID uint32
166 uniID uint32
167 tpID uint32
168 uniPort uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700169 tpInst interface{}
Gamze Abakafee36392019-10-03 11:17:24 +0000170 meterID uint32
khenaidoodc2116e2021-10-19 17:33:19 -0400171 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000172}
173
Gamze Abaka7650be62021-02-26 10:50:36 +0000174type flowContext struct {
175 intfID uint32
176 onuID uint32
177 uniID uint32
178 portNo uint32
179 classifier map[string]interface{}
180 action map[string]interface{}
181 logicalFlow *ofp.OfpFlowStats
182 allocID uint32
183 gemPortID uint32
184 tpID uint32
185 pbitToGem map[uint32]uint32
186 gemToAes map[uint32]bool
187}
188
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700189// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
190// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
191// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
192// flow and processes it serially
193type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400194 ctx context.Context // Flow handler context
195 addFlow bool // if true flow to be added, else removed
196 flow *ofp.OfpFlowStats // Flow message
197 flowMetadata *ofp.FlowMetadata // FlowMetadata that contains flow meter information. This can be nil for Flow remove
198 errChan *chan error // channel to report the Flow handling error
Esin Karamanccb714b2019-11-29 15:02:06 +0000199}
200
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700201//OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530202type OpenOltFlowMgr struct {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700203 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700204 techprofile tp.TechProfileIf
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700205 deviceHandler *DeviceHandler
206 grpMgr *OpenOltGroupMgr
207 resourceMgr *rsrcMgr.OpenOltResourceMgr
208
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 //packet in gem port local cache
210 packetInGemPortLock sync.RWMutex
211
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700212 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
213 // A go routine per ONU, waits on the unique channel (indexed by ONU ID) for incoming flows (add/remove)
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700214 incomingFlows []chan flowControlBlock
215 stopFlowHandlerRoutine []chan bool
216 flowHandlerRoutineActive []bool
manikkaraj kbf256be2019-03-25 00:13:48 +0530217}
218
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700219//NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700220func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000221 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530222 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530223 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530224
manikkaraj kbf256be2019-03-25 00:13:48 +0530225 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700226 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700227 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530228 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000229 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
230 if ponPortIdx != dh.totalPonPorts {
231 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
232 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
233 return nil
234 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530235 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530236 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700237
238 // Create a slice of buffered channels for handling concurrent flows per ONU.
239 // The additional entry (+1) is to handle the NNI trap flows on a separate channel from individual ONUs channel
Mahir Gunyel85f61c12021-10-06 11:53:45 -0700240 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
241 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
242 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700243 for i := range flowMgr.incomingFlows {
244 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800245 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246 // Spin up a go routine to handling incoming flows (add/remove).
247 // There will be on go routine per ONU.
248 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700249 flowMgr.flowHandlerRoutineActive[i] = true
250 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700251 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700252
Esin Karamanccb714b2019-11-29 15:02:06 +0000253 //load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700254 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000255 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530256 return &flowMgr
257}
258
Kent Hagermane6ff1012020-07-14 15:07:53 -0400259func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000260 // In case of nni trap flow
261 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000262 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000263 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700264 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
265 // Flow is not replicated in this case, we need to register the flow for a single gem-port
yasin saplibddc2d72022-02-08 13:10:17 +0000266 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700267 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
268 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
269 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000270 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700271 return err
272 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700273 }
Gamze Abakafee36392019-10-03 11:17:24 +0000274 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700275 return nil
276}
277
Girish Gowdra9602eb42020-09-09 15:50:39 -0700278func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000279 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400280 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000281 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530282 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700283 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530284
Neha Sharma96b7bf22020-06-15 10:37:32 +0000285 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530286 "device-id": f.deviceHandler.device.Id,
287 "intf-id": intfID,
288 "onu-id": onuID,
289 "uni-id": uniID,
290 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700291 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530292 "action": actionInfo,
293 "usmeter-iD": UsMeterID,
294 "dsmeter-iD": DsMeterID,
295 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400296 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
297 // is because the flow is an NNI flow and there would be no onu resources associated with it
298 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400299 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200300 cause := "no-onu-id-for-flow"
301 fields := log.Fields{
302 "onu": onuID,
303 "port-no": portNo,
304 "classifer": classifierInfo,
305 "action": actionInfo,
306 "device-id": f.deviceHandler.device.Id}
307 logger.Errorw(ctx, cause, fields)
308 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530309 }
310
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700311 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000312 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530313 "uni": uni,
314 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530315
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700316 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
317 "device-id": f.deviceHandler.device.Id,
318 "intf-id": intfID,
319 "onu-id": onuID,
320 "uni-id": uniID,
321 "port-no": portNo,
322 "classifier": classifierInfo,
323 "action": actionInfo,
324 "usmeter-id": UsMeterID,
325 "dsmeter-id": DsMeterID,
326 "tp-id": TpID})
327 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
328 if allocID == 0 || gemPorts == nil || TpInst == nil {
329 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
330 return olterrors.NewErrNotFound(
331 "alloc-id-gem-ports-tp-unavailable",
332 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400333 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700334 args := make(map[string]uint32)
335 args[IntfID] = intfID
336 args[OnuID] = onuID
337 args[UniID] = uniID
338 args[PortNo] = portNo
339 args[AllocID] = allocID
340
341 /* Flows can be added specific to gemport if p-bits are received.
342 * If no pbit mentioned then adding flows for all gemports
343 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000344 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530345}
346
salmansiddiqui7ac62132019-08-22 03:58:50 +0000347// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800348// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530349func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400350
Girish Gowdraf3728b12022-02-02 21:46:51 -0800351 logger.Infow(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530352 log.Fields{"dir": sq.direction,
353 "intf-id": sq.intfID,
354 "onu-id": sq.onuID,
355 "uni-id": sq.uniID,
356 "tp-id": sq.tpID,
357 "meter-id": sq.meterID,
358 "tp-inst": sq.tpInst,
359 "flowmetadata": sq.flowMetadata,
360 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400361
Girish Gowdra6071f382021-12-14 12:52:04 +0530362 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000363 if err != nil {
364 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400365 }
366
Girish Gowdraf3728b12022-02-02 21:46:51 -0800367 var TrafficShaping *tp_pb.TrafficShapingInfo
368 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
369 return olterrors.NewErrInvalidValue(log.Fields{
370 "reason": "invalid-meter-config",
371 "meter-id": sq.meterID,
372 "device-id": f.deviceHandler.device.Id}, nil)
373 }
374
375 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
376 return olterrors.NewErrInvalidValue(log.Fields{
377 "reason": "invalid-meter-config",
378 "meter-id": sq.meterID,
379 "device-id": f.deviceHandler.device.Id}, nil)
380 }
381
382 var SchedCfg *tp_pb.SchedulerConfig
383 if sq.direction == tp_pb.Direction_UPSTREAM {
384 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
385 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
386 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
387 }
388 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
389 TrafficSched[0].TechProfileId = sq.tpID
390
Manikkaraj kb1d51442019-07-23 10:41:02 -0400391 /* Lets make a simple assumption that if the meter-id is present on the KV store,
392 * then the scheduler and queues configuration is applied on the OLT device
393 * in the given direction.
394 */
yasin saplibddc2d72022-02-08 13:10:17 +0000395 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530397 return olterrors.NewErrNotFound("meter",
398 log.Fields{"intf-id": sq.intfID,
399 "onu-id": sq.onuID,
400 "uni-id": sq.uniID,
401 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000403
Girish Gowdraf3728b12022-02-02 21:46:51 -0800404 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530405 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800406 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530407 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000408 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800409 return err
410 }
411
412 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
413 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
414 // Just create gem ports and traffic queues on the current uni for the given service
415 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
416 log.Fields{"intf-id": sq.intfID,
417 "onu-id": sq.onuID,
418 "uni-id": sq.uniID,
419 "tp-id": sq.tpID,
420 "device-id": f.deviceHandler.device.Id})
421 // The upstream scheduler is already created. We only need to create the queues
422 // If there are multiple upstream flows on a given uni, then it is possible that
423 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
424 // TODO: Find better mechanism to not duplicate request.
425 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
426 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
427 log.Fields{"intf-id": sq.intfID,
428 "direction": sq.direction,
429 "device-id": f.deviceHandler.device.Id}, err)
430 }
431 } else {
432 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
433 log.Fields{"intf-id": sq.intfID,
434 "onu-id": sq.onuID,
435 "uni-id": sq.uniID,
436 "tp-id": sq.tpID,
437 "device-id": f.deviceHandler.device.Id})
438 }
439 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400440 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000441
Neha Sharma96b7bf22020-06-15 10:37:32 +0000442 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530443 log.Fields{
444 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530445 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530446 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000447
Girish Gowdraa482f272021-03-24 23:04:19 -0700448 found := false
449 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000450 if sq.flowMetadata != nil {
451 for _, meter := range sq.flowMetadata.Meters {
452 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700453 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700454 meterInfo.RefCnt = 1 // initialize it to 1, since this is the first flow that referenced the meter id.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000455 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700456 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530457 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400459 break
460 }
461 }
462 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000463 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400464 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530466 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800467 "reason": "Could-not-get-meterbands-from-flowMetadata",
468 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530469 "meter-id": sq.meterID,
470 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400471 }
Gamze Abaka01174422021-03-10 06:55:27 +0000472
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700473 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530474 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
475 log.Fields{"intf-id": sq.intfID,
476 "direction": sq.direction,
477 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400478 }
479
salmansiddiqui7ac62132019-08-22 03:58:50 +0000480 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 * store the meter id on the KV store, for further reference.
482 */
yasin saplibddc2d72022-02-08 13:10:17 +0000483 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530484 return olterrors.NewErrAdapter("failed-updating-meter-id",
485 log.Fields{"onu-id": sq.onuID,
486 "meter-id": sq.meterID,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000489 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530490 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700491 "meter-info": meterInfo,
492 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400493 return nil
494}
495
Girish Gowdraf3728b12022-02-02 21:46:51 -0800496func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
497 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
498 if err != nil {
499 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
500 log.Fields{"intf-id": sq.intfID,
501 "direction": sq.direction,
502 "device-id": f.deviceHandler.device.Id}, err)
503 }
504 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
505 log.Fields{"direction": sq.direction,
506 "traffic-queues": trafficQueues,
507 "device-id": f.deviceHandler.device.Id})
508 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
509 UniId: sq.uniID, PortNo: sq.uniPort,
510 TrafficQueues: trafficQueues,
511 TechProfileId: TrafficSched[0].TechProfileId}
512 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
513 if len(queues.TrafficQueues) > 1 {
514 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
515 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
516 }
517 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
518 }
519 return err
520}
521
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700522func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700523 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000524
525 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530526 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
527 log.Fields{"intf-id": sq.intfID,
528 "direction": sq.direction,
529 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000530 }
531
Gamze Abakacb0e6772021-06-10 08:32:12 +0000532 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
533 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
534 log.Fields{
535 "direction": sq.direction,
536 "TrafficScheds": TrafficSched,
537 "device-id": f.deviceHandler.device.Id,
538 "intfID": sq.intfID,
539 "onuID": sq.onuID,
540 "uniID": sq.uniID})
541 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
542 IntfId: sq.intfID, OnuId: sq.onuID,
543 UniId: sq.uniID, PortNo: sq.uniPort,
544 TrafficScheds: TrafficSched}); err != nil {
545 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
546 }
547 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
548 "direction": sq.direction,
549 "traffic-queues": trafficQueues,
550 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000551 }
552
553 // On receiving the CreateTrafficQueues request, the driver should create corresponding
554 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000555 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530556 log.Fields{"direction": sq.direction,
557 "traffic-queues": trafficQueues,
558 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000559 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
560 UniId: sq.uniID, PortNo: sq.uniPort,
561 TrafficQueues: trafficQueues,
562 TechProfileId: TrafficSched[0].TechProfileId}
563 if _, err := f.deviceHandler.Client.CreateTrafficQueues(ctx, queues); err != nil {
564 if len(queues.TrafficQueues) > 1 {
565 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
566 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(ctx, queues)
567 }
568 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530569 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000571 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530572 "direction": sq.direction,
573 "traffic-queues": trafficQueues,
574 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000575
Esin Karamanccb714b2019-11-29 15:02:06 +0000576 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700577 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000578 if len(multicastTrafficQueues) > 0 {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700579 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { //assumed that there is only one queue per PON for the multicast service
Esin Karamanccb714b2019-11-29 15:02:06 +0000580 //the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
581 //just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000582 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000583 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700584 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000585 gemPortID: multicastQueuePerPonPort.GemportId,
586 servicePriority: multicastQueuePerPonPort.Priority,
587 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700588 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Esin Karamanccb714b2019-11-29 15:02:06 +0000589 //also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000590 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700591 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400592 return err
593 }
Shrey Baid26912972020-04-16 21:02:31 +0530594
Neha Sharma96b7bf22020-06-15 10:37:32 +0000595 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000596 }
597 }
598 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000599 return nil
600}
601
Girish Gowdraf3728b12022-02-02 21:46:51 -0800602// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
603func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
604 var err error
605 logger.Infow(ctx, "removing-queue-in-olt",
606 log.Fields{
607 "direction": sq.direction,
608 "intf-id": sq.intfID,
609 "onu-id": sq.onuID,
610 "uni-id": sq.uniID,
611 "uni-port": sq.uniPort,
612 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400613
Girish Gowdraf3728b12022-02-02 21:46:51 -0800614 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
615 if err != nil {
616 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
617 log.Fields{
618 "intf-id": sq.intfID,
619 "direction": sq.direction,
620 "device-id": f.deviceHandler.device.Id}, err)
621 }
622
623 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
624 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
625 UniId: sq.uniID, PortNo: sq.uniPort,
626 TrafficQueues: TrafficQueues,
627 TechProfileId: sq.tpID}); err != nil {
628 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
629 log.Fields{
630 "intf-id": sq.intfID,
631 "traffic-queues": TrafficQueues,
632 "device-id": f.deviceHandler.device.Id}, err)
633 }
634 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
635
636 return err
637}
638
639// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
640func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400641 var Direction string
642 var SchedCfg *tp_pb.SchedulerConfig
643 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800644 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530645 log.Fields{
646 "direction": sq.direction,
647 "intf-id": sq.intfID,
648 "onu-id": sq.onuID,
649 "uni-id": sq.uniID,
650 "uni-port": sq.uniPort,
651 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000652 if sq.direction == tp_pb.Direction_UPSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700653 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400654 Direction = "upstream"
Gamze Abakafee36392019-10-03 11:17:24 +0000655 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700656 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400657 Direction = "downstream"
658 }
659
Girish Gowdraa482f272021-03-24 23:04:19 -0700660 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
Manikkaraj kb1d51442019-07-23 10:41:02 -0400661
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700662 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000663 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000664
Girish Gowdraf3728b12022-02-02 21:46:51 -0800665 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
666 IntfId: sq.intfID, OnuId: sq.onuID,
667 UniId: sq.uniID, PortNo: sq.uniPort,
668 TrafficScheds: TrafficSched}); err != nil {
669 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530670 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800671 "intf-id": sq.intfID,
672 "traffic-schedulers": TrafficSched,
673 "onu-id": sq.onuID,
674 "uni-id": sq.uniID,
675 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000676 }
Manikkaraj kb1d51442019-07-23 10:41:02 -0400677
Girish Gowdraf3728b12022-02-02 21:46:51 -0800678 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
679 log.Fields{"device-id": f.deviceHandler.device.Id,
680 "intf-id": sq.intfID,
681 "onu-id": sq.onuID,
682 "uni-id": sq.uniID,
683 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684
Girish Gowdraf3728b12022-02-02 21:46:51 -0800685 if sq.direction == tp_pb.Direction_UPSTREAM {
686 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
687 // Delete the TCONT on the ONU.
688 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000689 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -0800690 if err := f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
691 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000692 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800693 "intf": sq.intfID,
694 "onu-id": sq.onuID,
695 "uni-id": sq.uniID,
696 "device-id": f.deviceHandler.device.Id,
697 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000698 }
699 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000700
701 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400702 * delete the meter id on the KV store.
703 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800704 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400705 return err
706}
707
Girish Gowdra197acc12021-08-16 10:59:45 -0700708// We are trying to force remove the schedulers and queues here if one exists for the given key.
709// We ignore any errors encountered in the process. The errors most likely are encountered when
710// the schedulers and queues are already cleared for the given key.
711func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
712
713 var schedCfg *tp_pb.SchedulerConfig
714 var err error
715 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
716 log.Fields{
717 "direction": sq.direction,
718 "intf-id": sq.intfID,
719 "onu-id": sq.onuID,
720 "uni-id": sq.uniID,
721 "uni-port": sq.uniPort,
722 "tp-id": sq.tpID,
723 "device-id": f.deviceHandler.device.Id})
724 if sq.direction == tp_pb.Direction_UPSTREAM {
725 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
726 } else if sq.direction == tp_pb.Direction_DOWNSTREAM {
727 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
728 }
729
730 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
731 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
732 TrafficSched[0].TechProfileId = sq.tpID
733
734 // Remove traffic queues. Ignore any errors, just log them.
735 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
736 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
737 "direction": sq.direction,
738 "intf-id": sq.intfID,
739 "onu-id": sq.onuID,
740 "uni-id": sq.uniID,
741 "uni-port": sq.uniPort,
742 "tp-id": sq.tpID,
743 "device-id": f.deviceHandler.device.Id,
744 "err": err})
745 } else {
746 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(ctx,
747 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
748 UniId: sq.uniID, PortNo: sq.uniPort,
749 TrafficQueues: TrafficQueues,
750 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
751 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
752 "direction": sq.direction,
753 "intf-id": sq.intfID,
754 "onu-id": sq.onuID,
755 "uni-id": sq.uniID,
756 "uni-port": sq.uniPort,
757 "tp-id": sq.tpID,
758 "device-id": f.deviceHandler.device.Id,
759 "err": err})
760
761 } else {
762 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
763 "direction": sq.direction,
764 "intf-id": sq.intfID,
765 "onu-id": sq.onuID,
766 "uni-id": sq.uniID,
767 "uni-port": sq.uniPort,
768 "tp-id": sq.tpID})
769 }
770 }
771
772 // Remove traffic schedulers. Ignore any errors, just log them.
773 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
774 IntfId: sq.intfID, OnuId: sq.onuID,
775 UniId: sq.uniID, PortNo: sq.uniPort,
776 TrafficScheds: TrafficSched}); err != nil {
777 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
778 "direction": sq.direction,
779 "intf-id": sq.intfID,
780 "onu-id": sq.onuID,
781 "uni-id": sq.uniID,
782 "uni-port": sq.uniPort,
783 "tp-id": sq.tpID,
784 "device-id": f.deviceHandler.device.Id,
785 "err": err})
786 } else {
787 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
788 "direction": sq.direction,
789 "intf-id": sq.intfID,
790 "onu-id": sq.onuID,
791 "uni-id": sq.uniID,
792 "uni-port": sq.uniPort,
793 "tp-id": sq.tpID})
794 }
795}
796
Gamze Abakafee36392019-10-03 11:17:24 +0000797// This function allocates tconts and GEM ports for an ONU
khenaidoodc2116e2021-10-19 17:33:19 -0400798func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, uniPort uint32, TpID uint32, UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) (uint32, []uint32, interface{}) {
Gamze Abakafee36392019-10-03 11:17:24 +0000799 var allocIDs []uint32
800 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530801 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530802 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000803 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000804 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
805 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
806 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530807
Neha Sharma96b7bf22020-06-15 10:37:32 +0000808 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530809 "intf-id": intfID,
810 "onu-id": onuID,
811 "uni-id": uniID,
812 "device-id": f.deviceHandler.device.Id,
813 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530814
Manikkaraj kb1d51442019-07-23 10:41:02 -0400815 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700816 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000817 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000818 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530819 log.Fields{
820 "path": tpPath,
821 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700822 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000823 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530824 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000825 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530826 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700827 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530828 "tp-id": TpID,
829 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000830 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530831 }
yasin saplibddc2d72022-02-08 13:10:17 +0000832 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700833 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400834 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000836 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530837 log.Fields{
838 "uni": uni,
839 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530840 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530841 }
Gamze Abakafee36392019-10-03 11:17:24 +0000842
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700843 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700844 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700845 if UsMeterID != 0 {
846 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
847 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
848 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000849 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700850 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700851 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700852 "onu-id": onuID,
853 "uni-id": uniID,
854 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700855 "meter-id": UsMeterID,
856 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000857 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700858 return 0, nil, nil
859 }
860 }
861 if DsMeterID != 0 {
862 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: TpID,
863 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
864 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000865 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700866 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700868 "onu-id": onuID,
869 "uni-id": uniID,
870 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700871 "meter-id": DsMeterID,
872 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000873 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700874 return 0, nil, nil
875 }
876 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700877 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700878 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700879 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700881 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000882
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700883 if tpInstanceExists {
884 return allocID, gemPortIDs, techProfileInstance
885 }
886
887 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700888 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000890 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700891 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700892 "intf-id": intfID,
893 "onu-id": onuID,
894 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 "alloc-ids": allocIDs,
896 "gemports": allgemPortIDs,
897 "device-id": f.deviceHandler.device.Id})
898 // Send Tconts and GEM ports to KV store
899 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530900 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400901 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700902 // CreateSchedulerQueues for EPON needs to be implemented here
903 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700906 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700907 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700908 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700909
910 if tpInstanceExists {
911 return allocID, gemPortIDs, techProfileInstance
912 }
913
914 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700915 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700916 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000917 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700918 log.Fields{
919 "alloc-ids": allocIDs,
920 "gemports": allgemPortIDs,
921 "device-id": f.deviceHandler.device.Id})
922 // Send Tconts and GEM ports to KV store
923 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
924 return allocID, gemPortIDs, techProfileInstance
925 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000926 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700927 log.Fields{
928 "tpInst": tpInst})
929 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530930 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530931}
932
npujarec5762e2020-01-01 14:08:48 +0530933func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
manikkaraj kbf256be2019-03-25 00:13:48 +0530934
Neha Sharma96b7bf22020-06-15 10:37:32 +0000935 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530936 log.Fields{
937 "intf-id": intfID,
938 "onu-id": onuID,
939 "uni-id": uniID,
940 "alloc-id": allocID,
941 "gemport-ids": gemPortIDs,
942 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530943 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000944 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000945 logger.Errorw(ctx, "error-while-uploading-allocid-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "allocID": allocID})
manikkaraj kbf256be2019-03-25 00:13:48 +0530946 }
yasin saplibddc2d72022-02-08 13:10:17 +0000947 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000948 logger.Errorw(ctx, "error-while-uploading-gemports-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPortIDs})
manikkaraj kbf256be2019-03-25 00:13:48 +0530949 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700950
Neha Sharma96b7bf22020-06-15 10:37:32 +0000951 logger.Infow(ctx, "stored-tconts-and-gem-into-kv-store-successfully", log.Fields{"device-id": f.deviceHandler.device.Id})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400952 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000953 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000954 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
955 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400956 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530957}
958
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700959func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530960 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000961 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700962 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
963 var err error
964 f.techprofile, err = tp.NewTechProfile(ctx, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
965 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
966 if err != nil || f.techprofile == nil {
967 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
968 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
969 }
970 logger.Debugw(ctx, "init-tech-profile-done",
971 log.Fields{
972 "intf-id": intfID,
973 "device-id": f.deviceHandler.device.Id})
974 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -0700975 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 }
977 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700978 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
979 return fmt.Errorf("pon-port-idx-not-found-in-the-device-info-pon-port-range-%v", f.ponPortIdx)
manikkaraj kbf256be2019-03-25 00:13:48 +0530980}
981
Gamze Abaka7650be62021-02-26 10:50:36 +0000982func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -0800983 flowContext.classifier[PacketTagType] = SingleTag
984 // extract the cvid/inner-vid from the write metadata
985 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
986 if writeMetadata != 0 {
987 // Writemetadata field is 8 bytes
988 // cvid is on the outer most two bytes of the write metadata
989 cvid := (writeMetadata & 0xffff000000000000) >> 48
990 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
991 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
992 flowContext.classifier[PacketTagType] = DoubleTag
993 }
994 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000995 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +0530996 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +0000997 "uplinkClassifier": flowContext.classifier,
998 "uplinkAction": flowContext.action})
999 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301000}
1001
Gamze Abaka7650be62021-02-26 10:50:36 +00001002func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1003 downlinkClassifier := flowContext.classifier
1004 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001005 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1006 downlinkClassifier[PacketTagType] = SingleTag
1007 // extract the cvid/inner-vid from the write metadata
1008 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1009 if writeMetadata != 0 {
1010 // Writemetadata field is 8 bytes
1011 // cvid is on the outer most two bytes of the write metadata
1012 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1013 downlinkClassifier[PacketTagType] = DoubleTag
1014 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301015 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001016 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301017 log.Fields{
1018 "downlinkClassifier": downlinkClassifier,
1019 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001020
Girish Gowdraffa52e52022-02-16 15:48:10 -08001021 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1022 // The matched vlan is the one that is getting popped.
1023 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1024 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1025 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1026 if ok {
1027 downlinkAction[VlanVid] = dlClVid & 0xfff
1028 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301029 }
1030
Gamze Abaka7650be62021-02-26 10:50:36 +00001031 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301032}
1033
Gamze Abaka7650be62021-02-26 10:50:36 +00001034func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001035
Gamze Abaka7650be62021-02-26 10:50:36 +00001036 intfID := flowContext.intfID
1037 onuID := flowContext.onuID
1038 uniID := flowContext.uniID
1039 classifier := flowContext.classifier
1040 action := flowContext.action
1041 allocID := flowContext.allocID
1042 gemPortID := flowContext.gemPortID
1043 tpID := flowContext.tpID
1044 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001045 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301046 log.Fields{
1047 "intf-id": intfID,
1048 "onu-id": onuID,
1049 "uni-id": uniID,
1050 "device-id": f.deviceHandler.device.Id,
1051 "classifier": classifier,
1052 "action": action,
1053 "direction": direction,
1054 "alloc-id": allocID,
1055 "gemport-id": gemPortID,
1056 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001057
yasin saplibddc2d72022-02-08 13:10:17 +00001058 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001059 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001060 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301061 log.Fields{
1062 "device-id": f.deviceHandler.device.Id,
1063 "intf-id": intfID,
1064 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001065 return nil
yasin saplid0566272021-12-21 09:10:30 +00001066 } else if err != nil {
1067 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1068 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1069 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301070 }
yasin saplid0566272021-12-21 09:10:30 +00001071
David K. Bainbridge794735f2020-02-11 21:01:37 -08001072 classifierProto, err := makeOpenOltClassifierField(classifier)
1073 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301074 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "classifier": *classifierProto,
1079 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001080 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301082 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301083 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001084 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301085 log.Fields{
1086 "action": *actionProto,
1087 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001088 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301089 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301090 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001091 log.Fields{
1092 "classifier": classifier,
1093 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301094 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301096 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001097
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001098 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001099 OnuId: int32(onuID),
1100 UniId: int32(uniID),
1101 FlowId: logicalFlow.Id,
1102 FlowType: direction,
1103 AllocId: int32(allocID),
1104 NetworkIntfId: int32(networkIntfID),
1105 GemportId: int32(gemPortID),
1106 Classifier: classifierProto,
1107 Action: actionProto,
1108 Priority: int32(logicalFlow.Priority),
1109 Cookie: logicalFlow.Cookie,
1110 PortNo: flowContext.portNo,
1111 TechProfileId: tpID,
1112 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1113 PbitToGemport: flowContext.pbitToGem,
1114 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001115 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001116 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001117 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301118 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001119 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301120 log.Fields{"direction": direction,
1121 "device-id": f.deviceHandler.device.Id,
1122 "flow": flow,
1123 "intf-id": intfID,
1124 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001125
David K. Bainbridge794735f2020-02-11 21:01:37 -08001126 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301127}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001128
Gamze Abaka7650be62021-02-26 10:50:36 +00001129func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1130
1131 intfID := flowContext.intfID
1132 onuID := flowContext.onuID
1133 uniID := flowContext.uniID
1134 logicalFlow := flowContext.logicalFlow
1135 classifier := flowContext.classifier
1136 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301137
Neha Sharma96b7bf22020-06-15 10:37:32 +00001138 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301139 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301140 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001141 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301142 "action": action,
1143 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001144 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301145 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301146
1147 // Clear the action map
1148 for k := range action {
1149 delete(action, k)
1150 }
1151
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001152 action[TrapToHost] = true
1153 classifier[UDPSrc] = uint32(68)
1154 classifier[UDPDst] = uint32(67)
1155 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301156
yasin saplibddc2d72022-02-08 13:10:17 +00001157 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001158 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001159 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301160 log.Fields{
1161 "device-id": f.deviceHandler.device.Id,
1162 "intf-id": intfID,
1163 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001164 return nil
yasin saplid0566272021-12-21 09:10:30 +00001165 } else if err != nil {
1166 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1167 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1168 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301169 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301170
Neha Sharma96b7bf22020-06-15 10:37:32 +00001171 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301172 log.Fields{
1173 "ul_classifier": classifier,
1174 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001175 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301176 "intf-id": intfID,
1177 "onu-id": onuID,
1178 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301179
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 classifierProto, err := makeOpenOltClassifierField(classifier)
1181 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301182 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301183 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001184 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001185 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001186 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301187 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188 }
1189
David K. Bainbridge794735f2020-02-11 21:01:37 -08001190 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001191 OnuId: int32(onuID),
1192 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001193 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001194 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001195 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001196 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001197 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301198 Classifier: classifierProto,
1199 Action: actionProto,
1200 Priority: int32(logicalFlow.Priority),
1201 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001202 PortNo: flowContext.portNo,
1203 TechProfileId: flowContext.tpID,
1204 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1205 PbitToGemport: flowContext.pbitToGem,
1206 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001207 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001208 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001211 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301212 log.Fields{
1213 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001214 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301215 "intf-id": intfID,
1216 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301217
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301219}
1220
Esin Karamanae41e2b2019-12-17 18:13:13 +00001221//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001222func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1223 delete(flowContext.classifier, VlanVid)
1224 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001225}
1226
1227//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001228func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1229
1230 intfID := flowContext.intfID
1231 onuID := flowContext.onuID
1232 uniID := flowContext.uniID
1233 logicalFlow := flowContext.logicalFlow
1234 classifier := flowContext.classifier
1235 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001236
Neha Sharma96b7bf22020-06-15 10:37:32 +00001237 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001238 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301239 return olterrors.NewErrNotFound("nni-interface-id",
1240 log.Fields{
1241 "classifier": classifier,
1242 "action": action,
1243 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001244 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001245 }
1246
1247 // Clear the action map
1248 for k := range action {
1249 delete(action, k)
1250 }
1251
1252 action[TrapToHost] = true
1253 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254
yasin saplibddc2d72022-02-08 13:10:17 +00001255 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001256 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001257 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001258 return nil
yasin saplid0566272021-12-21 09:10:30 +00001259 } else if err != nil {
1260 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1261 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1262 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001263 }
1264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301266 log.Fields{
1267 "ul_classifier": classifier,
1268 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001269 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301270 "device-id": f.deviceHandler.device.Id,
1271 "intf-id": intfID,
1272 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 classifierProto, err := makeOpenOltClassifierField(classifier)
1275 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301276 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001277 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001278 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301279 log.Fields{
1280 "classifier": *classifierProto,
1281 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001282 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001283 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301284 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285 }
1286
David K. Bainbridge794735f2020-02-11 21:01:37 -08001287 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001288 OnuId: int32(onuID),
1289 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001290 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001292 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001294 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001295 Classifier: classifierProto,
1296 Action: actionProto,
1297 Priority: int32(logicalFlow.Priority),
1298 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001299 PortNo: flowContext.portNo,
1300 TechProfileId: flowContext.tpID,
1301 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1302 PbitToGemport: flowContext.pbitToGem,
1303 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001304 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305
David K. Bainbridge794735f2020-02-11 21:01:37 -08001306 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001307 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": flow, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001308 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309
David K. Bainbridge794735f2020-02-11 21:01:37 -08001310 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311}
1312
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001313// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001314func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1315 intfID := flowContext.intfID
1316 onuID := flowContext.onuID
1317 uniID := flowContext.uniID
1318 portNo := flowContext.portNo
1319 allocID := flowContext.allocID
1320 gemPortID := flowContext.gemPortID
1321 logicalFlow := flowContext.logicalFlow
1322 classifier := flowContext.classifier
1323 action := flowContext.action
1324
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001325 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301326 log.Fields{
1327 "intf-id": intfID,
1328 "onu-id": onuID,
1329 "port-no": portNo,
1330 "alloc-id": allocID,
1331 "gemport-id": gemPortID,
1332 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001333 "flow": logicalFlow,
1334 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301335
1336 uplinkClassifier := make(map[string]interface{})
1337 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301338
manikkaraj kbf256be2019-03-25 00:13:48 +05301339 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001340 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001341 uplinkClassifier[PacketTagType] = SingleTag
1342 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001343 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301344 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001345 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001346 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001347 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001348 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301349 "device-id": f.deviceHandler.device.Id,
1350 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001351 "intf-id": intfID,
1352 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001353 return nil
yasin saplid0566272021-12-21 09:10:30 +00001354 } else if err != nil {
1355 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1356 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1357 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301358 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001359 //Add Uplink EthType Flow
1360 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301361 log.Fields{
1362 "ul_classifier": uplinkClassifier,
1363 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001364 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "intf-id": intfID,
1367 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301368
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1370 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301371 return olterrors.NewErrInvalidValue(log.Fields{
1372 "classifier": uplinkClassifier,
1373 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001375 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301376 log.Fields{
1377 "classifier": *classifierProto,
1378 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001379 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001380 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301381 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301382 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001383 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301384 log.Fields{
1385 "action": *actionProto,
1386 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001387 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301388 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301389 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001390 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301391 "action": action,
1392 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001393 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301394 }
1395
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001397 OnuId: int32(onuID),
1398 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001399 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001400 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001401 AllocId: int32(allocID),
1402 NetworkIntfId: int32(networkIntfID),
1403 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 Classifier: classifierProto,
1405 Action: actionProto,
1406 Priority: int32(logicalFlow.Priority),
1407 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001408 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001409 TechProfileId: flowContext.tpID,
1410 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1411 PbitToGemport: flowContext.pbitToGem,
1412 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001413 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001414 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001416 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001417 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301418 log.Fields{
1419 "device-id": f.deviceHandler.device.Id,
1420 "onu-id": onuID,
1421 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001422 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301423 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001424
David K. Bainbridge794735f2020-02-11 21:01:37 -08001425 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301426}
1427
David K. Bainbridge794735f2020-02-11 21:01:37 -08001428func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430
1431 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1432 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1433 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001434 if vlanID != ReservedVlan {
1435 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001436 classifier.OVid = vid
1437 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301438 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001439 // The classifierInfo[Metadata] is set for the following flows
1440 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1441 // - Mcast flow that points to a group in the treatment
1442 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1443 // - inner vid for a double tagged packet in the datapath flow
1444 // - outer vid for a single tagged packet in the datapath flow
1445 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1447 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301448 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1449 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1450 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1451 // becomes the IVid.
1452 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1453 if vid != ReservedVlan {
1454 classifier.IVid = vid
1455 }
1456 } else {
1457 if vid != ReservedVlan {
1458 classifier.OVid = vid
1459 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001460 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301461 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301462 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001463 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301464 classifier.OPbits = vlanPcp
1465 } else {
1466 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301467 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001468 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1469 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1470 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1471 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001472 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001473 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001474 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1475 classifier.PktTagType = pktTagType
1476
1477 switch pktTagType {
1478 case SingleTag:
1479 case DoubleTag:
1480 case Untagged:
1481 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001482 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301483 }
1484 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001485 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301486}
1487
Gamze Abaka724d0852020-03-18 12:10:24 +00001488func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001489 var actionCmd openoltpb2.ActionCmd
1490 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301491 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001492 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001493 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301494 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001495 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001496 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001497 action.Cmd.RemarkInnerPbits = true
1498 action.IPbits = actionInfo[VlanPcp].(uint32)
1499 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001500 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001501 action.Cmd.TranslateInnerTag = true
1502 action.IVid = actionInfo[VlanVid].(uint32)
1503 }
1504 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001505 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001506 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001507 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301508 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001509 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001510 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001511 action.OPbits = actionInfo[VlanPcp].(uint32)
1512 action.Cmd.RemarkOuterPbits = true
1513 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001514 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001515 action.IVid = classifierInfo[VlanVid].(uint32)
1516 action.Cmd.TranslateInnerTag = true
1517 }
1518 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 } else if _, ok := actionInfo[TrapToHost]; ok {
1520 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001521 } else if _, ok := actionInfo[VlanVid]; ok {
1522 // Translate outer vid
1523 action.Cmd.TranslateOuterTag = true
1524 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301525 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301526 // When OLT is transparent to vlans no-action is valid.
1527 /*
1528 else {
1529 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1530 }
1531 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001532 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301533}
1534
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001535// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001536func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001537 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301538}
1539
Gamze Abakafee36392019-10-03 11:17:24 +00001540// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001541// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1542// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1543// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1544// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1545// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1546// because it was observed that if the ONU device was deleted too soon after the flows were
1547// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1548// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1549// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001550func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001551 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001552 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1553
Gamze Abakafee36392019-10-03 11:17:24 +00001554 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001555
1556 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001557 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001558 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001559 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001560 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1561 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1562 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1563 log.Fields{
1564 "tp-id": tpID,
1565 "path": tpPath})
1566 }
1567 switch tpInstance := tpInst.(type) {
1568 case *tp_pb.TechProfileInstance:
1569 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1570 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1571 }
1572 // Force cleanup scheduler/queues -- end
1573
1574 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301575 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001576 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301577 // return err
1578 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001579 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001580 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 +00001581 }
1582 return nil
1583}
1584
1585// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301586func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001587 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001588 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001589 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301591 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1592 log.Fields{
1593 "tp-id": tpID,
1594 "uni-port-name": uniPortName,
1595 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001596 }
1597 return nil
1598}
1599
David K. Bainbridge794735f2020-02-11 21:01:37 -08001600func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001601
1602 var intfID uint32
1603 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1604 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1605 */
1606 if deviceFlow.AccessIntfId != -1 {
1607 intfID = uint32(deviceFlow.AccessIntfId)
1608 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001609 // We need to log the valid interface ID.
1610 // 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 +00001611 intfID = uint32(deviceFlow.NetworkIntfId)
1612 }
1613
Neha Sharma96b7bf22020-06-15 10:37:32 +00001614 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301615 "flow": *deviceFlow,
1616 "device-id": f.deviceHandler.device.Id,
1617 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001618 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001619
1620 st, _ := status.FromError(err)
1621 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001622 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001623 "err": err,
1624 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301625 "device-id": f.deviceHandler.device.Id,
1626 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001627 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301628 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001631 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301632 log.Fields{"err": err,
1633 "device-flow": deviceFlow,
1634 "device-id": f.deviceHandler.device.Id,
1635 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001636 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001637 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001638 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301639 log.Fields{
1640 "flow": *deviceFlow,
1641 "device-id": f.deviceHandler.device.Id,
1642 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001643
yasin saplid0566272021-12-21 09:10:30 +00001644 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1645 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1646 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001647 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001648 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001649}
1650
Neha Sharma96b7bf22020-06-15 10:37:32 +00001651func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1652 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301653 log.Fields{
1654 "flow": *deviceFlow,
1655 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001656 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001657 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001658 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001659 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301660 log.Fields{
1661 "err": err,
1662 "deviceFlow": deviceFlow,
1663 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001664 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001665 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001666 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001667 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001668
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001669 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001671 "of-flow-id": ofFlowID,
1672 "flow": *deviceFlow,
1673 "device-id": f.deviceHandler.device.Id,
1674 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301676}
1677
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001679
1680 classifierInfo := make(map[string]interface{})
1681 actionInfo := make(map[string]interface{})
1682
1683 classifierInfo[EthType] = uint32(LldpEthType)
1684 classifierInfo[PacketTagType] = Untagged
1685 actionInfo[TrapToHost] = true
1686
1687 // LLDP flow is installed to trap LLDP packets on the NNI port.
1688 // We manage flow_id resource pool on per PON port basis.
1689 // Since this situation is tricky, as a hack, we pass the NNI port
1690 // index (network_intf_id) as PON port Index for the flow_id resource
1691 // pool. Also, there is no ONU Id available for trapping LLDP packets
1692 // on NNI port, use onu_id as -1 (invalid)
1693 // ****************** CAVEAT *******************
1694 // This logic works if the NNI Port Id falls within the same valid
1695 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1696 // we need to have a re-look at this.
1697 // *********************************************
1698
1699 var onuID = -1
1700 var uniID = -1
1701 var gemPortID = -1
1702
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001703 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001704 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301705 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 }
yasin saplibddc2d72022-02-08 13:10:17 +00001707 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001708 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001709 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001710 return nil
yasin saplid0566272021-12-21 09:10:30 +00001711 } else if err != nil {
1712 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1713 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1714 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001715 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001716
David K. Bainbridge794735f2020-02-11 21:01:37 -08001717 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1718 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301719 return olterrors.NewErrInvalidValue(
1720 log.Fields{
1721 "classifier": classifierInfo,
1722 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001723 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001724 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301725 log.Fields{
1726 "classifier": *classifierProto,
1727 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001728 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001729 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301730 return olterrors.NewErrInvalidValue(
1731 log.Fields{
1732 "action": actionInfo,
1733 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001734 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001735 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301736 log.Fields{
1737 "action": *actionProto,
1738 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001739
1740 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1741 OnuId: int32(onuID), // OnuId not required
1742 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001743 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 FlowType: Downstream,
1745 NetworkIntfId: int32(networkInterfaceID),
1746 GemportId: int32(gemPortID),
1747 Classifier: classifierProto,
1748 Action: actionProto,
1749 Priority: int32(flow.Priority),
1750 Cookie: flow.Cookie,
1751 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001752 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001753 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301754 log.Fields{
1755 "flow": downstreamflow,
1756 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001757 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001758 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301759 log.Fields{
1760 "device-id": f.deviceHandler.device.Id,
1761 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001762 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001763
David K. Bainbridge794735f2020-02-11 21:01:37 -08001764 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301765}
1766
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001767func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1768 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001769}
1770
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001771//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001772func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001773 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1774 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1775 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001776 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301777 log.Fields{
1778 "intf-id": intfID,
1779 "onu-id": onuID,
1780 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001781 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001782 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301783 return nil, olterrors.NewErrNotFound("onu-child-device",
1784 log.Fields{
1785 "onu-id": onuID,
1786 "intf-id": intfID,
1787 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001788 }
khenaidoo106c61a2021-08-11 18:05:46 -04001789 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 -07001790 //better to ad the device to cache here.
1791 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1792 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001793 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301794 log.Fields{
1795 "intf-id": intfID,
1796 "onu-id": onuID,
1797 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
1799
1800 return onuDev.(*OnuDevice), nil
1801}
1802
1803//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1805 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301806 log.Fields{
1807 "pon-port": intfID,
1808 "onu-id": onuID,
1809 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001810 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001812 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301813 return nil, olterrors.NewErrNotFound("onu",
1814 log.Fields{
1815 "interface-id": parentPortNo,
1816 "onu-id": onuID,
1817 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001818 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301819 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001820 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301821 log.Fields{
1822 "device-id": f.deviceHandler.device.Id,
1823 "child_device_id": onuDevice.Id,
1824 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301825 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301826}
1827
Neha Sharma96b7bf22020-06-15 10:37:32 +00001828func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1829 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301830 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001831 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301832 log.Fields{
1833 "intf-id": intfID,
1834 "onu-id": onuID,
1835 "uni-id": uniID,
1836 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001837 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301838 }
1839
khenaidoodc2116e2021-10-19 17:33:19 -04001840 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001841 DeviceId: onuDev.deviceID,
1842 UniId: uniID,
1843 TpInstancePath: tpPath,
1844 GemPortId: gemPortID,
1845 }
1846 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1847
1848 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301849 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1850 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001851 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1852 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301853 "onu-id": onuDev.deviceID,
1854 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001855 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301856 }
khenaidoo106c61a2021-08-11 18:05:46 -04001857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301859 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001860 "msg": delGemPortMsg,
1861 "from-adapter": f.deviceHandler.device.Type,
1862 "to-adapter": onuDev.deviceType,
1863 "device-id": f.deviceHandler.device.Id,
1864 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301865 return nil
1866}
1867
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1869 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301870 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001871 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301872 log.Fields{
1873 "intf-id": intfID,
1874 "onu-id": onuID,
1875 "uni-id": uniID,
1876 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001877 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301878 }
1879
khenaidoodc2116e2021-10-19 17:33:19 -04001880 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001881 DeviceId: onuDev.deviceID,
1882 UniId: uniID,
1883 TpInstancePath: tpPath,
1884 AllocId: allocID,
1885 }
1886
Neha Sharma96b7bf22020-06-15 10:37:32 +00001887 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301888 log.Fields{
1889 "msg": *delTcontMsg,
1890 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001891
1892 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301893 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1894 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001895 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1896 "to-adapter": onuDev.adapterEndpoint,
1897 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301898 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001899 "device-id": f.deviceHandler.device.Id}, err)
1900
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001902 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301903 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001904 "msg": delTcontMsg,
1905 "device-id": f.deviceHandler.device.Id,
1906 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301907 return nil
1908}
1909
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301910//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001911// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001912func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001913 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001914
1915 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001916
Girish Gowdraa482f272021-03-24 23:04:19 -07001917 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001918 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001919 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1920 log.Fields{
1921 "tpPath": tpPath,
1922 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001923
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001924 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001925 if err != nil || techprofileInst == nil {
1926 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1927 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1928 if childDevice == nil {
1929 // happens when subscriber un-provision is immediately followed by child device delete
1930 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1931 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1932 return nil
1933 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001934 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1935 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001936 log.Fields{
1937 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001938 "path": tpPath}, err).Log()
1939 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001940 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001941
1942 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001943 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001944 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001945 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1946 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001947 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1948 if err != nil {
1949 return err
1950 }
1951 used := false
1952 for _, id := range flowIDs {
1953 if flowID != id {
1954 used = true
1955 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001956 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001957 }
1958 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001959 for i, flowIDinMap := range flowIDs {
1960 if flowIDinMap == flowID {
1961 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001962 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001963 return err
1964 }
1965 break
1966 }
1967 }
1968 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1969 log.Fields{
1970 "gemport-id": gemPortID,
1971 "usedByFlows": flowIDs,
1972 "currentFlow": flowID,
1973 "device-id": f.deviceHandler.device.Id})
1974 allGemPortsFree = false
1975 }
1976 }
1977 if !allGemPortsFree {
1978 return nil
1979 }
1980 }
1981
1982 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 -08001983
1984 // 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 +00001985 switch techprofileInst := techprofileInst.(type) {
1986 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08001987 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1988 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00001989 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08001990
yasin saplibddc2d72022-02-08 13:10:17 +00001991 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001992 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
1993 log.Fields{
1994 "err": err,
1995 "intf": intfID,
1996 "onu-id": onuID,
1997 "uni-id": uniID,
1998 "device-id": f.deviceHandler.device.Id,
1999 "gemport-id": gemPortID})
2000 }
2001
2002 }
2003 // Remove queues at OLT in upstream and downstream direction
2004 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2005 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2006 logger.Warn(ctx, err)
2007 }
2008 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2009 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2010 logger.Warn(ctx, err)
2011 }
2012 }
2013
2014 switch techprofileInst := techprofileInst.(type) {
2015 case *tp_pb.TechProfileInstance:
2016 // 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 +01002017 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2018 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2019 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002020 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002021 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002022 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002023 logger.Warn(ctx, err)
2024 }
2025 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002026 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002027 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002028 } else {
2029 // just remove meter reference for the upstream direction for the current pon/onu/uni
2030 // 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
2031 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2032 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002033 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002034 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2035 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002036 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002037 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002038
Girish Gowdraf3728b12022-02-02 21:46:51 -08002039 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2040 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002041 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002042 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2043 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002044 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002045 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002046 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002047 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002048 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002049 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302050 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002051 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302052 "onu-id": onuID,
2053 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002054 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002055 "alloc-id": techprofileInst.AllocId,
2056 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002057 }
yasin saplibddc2d72022-02-08 13:10:17 +00002058 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302059 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2060 logger.Warn(ctx, err)
2061 }
2062 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2063 logger.Warn(ctx, err)
2064 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002065 default:
2066 logger.Errorw(ctx, "error-unknown-tech",
2067 log.Fields{
2068 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002069 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002070
2071 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2072 switch techprofileInst := techprofileInst.(type) {
2073 case *tp_pb.TechProfileInstance:
2074 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2075 // Delete the gem port on the ONU.
2076 if sendDeleteGemRequest {
2077 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2078 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2079 log.Fields{
2080 "err": err,
2081 "intfID": intfID,
2082 "onu-id": onuID,
2083 "uni-id": uniID,
2084 "device-id": f.deviceHandler.device.Id,
2085 "gemport-id": gemPort.GemportId})
2086 }
yasin saplibddc2d72022-02-08 13:10:17 +00002087 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002088 }
2089 }
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302090 //Delete the tp instance and the techprofileid for onu at the end
2091 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2092 logger.Warn(ctx, err)
2093 }
2094 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2095 logger.Warn(ctx, err)
2096 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002097 }
2098
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302099 return nil
2100}
2101
David K. Bainbridge794735f2020-02-11 21:01:37 -08002102// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002103func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002104 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302105 log.Fields{
2106 "flowDirection": flowDirection,
2107 "flow": *flow,
2108 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002109
2110 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002111 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002112 }
2113
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302114 var ethType, ipProto, inPort uint32
2115 for _, field := range flows.GetOfbFields(flow) {
2116 if field.Type == flows.IP_PROTO {
2117 ipProto = field.GetIpProto()
2118 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2119 } else if field.Type == flows.ETH_TYPE {
2120 ethType = field.GetEthType()
2121 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2122 } else if field.Type == flows.IN_PORT {
2123 inPort = field.GetPort()
2124 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2125 }
2126 }
2127 portType := plt.IntfIDToPortTypeName(inPort)
2128 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2129 (portType == voltha.Port_ETHERNET_NNI) {
2130 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2131 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2132 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2133 // No more processing needed for trap from nni flows.
2134 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302135
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302136 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302137 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002138 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002139 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302140 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002141 onuID := int32(onu)
2142 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002143 tpID, err := getTpIDFromFlow(ctx, flow)
2144 if err != nil {
2145 return olterrors.NewErrNotFound("tp-id",
2146 log.Fields{
2147 "flow": flow,
2148 "intf-id": Intf,
2149 "onu-id": onuID,
2150 "uni-id": uniID,
2151 "device-id": f.deviceHandler.device.Id}, err)
2152 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302153
Neha Sharma96b7bf22020-06-15 10:37:32 +00002154 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302155 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002156 "flow-id": flow.Id,
2157 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302158 "onu-id": onuID,
2159 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302160
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002161 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2162 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002163 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2164 return err
2165 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002166
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002167 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002168 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2169 "flow-id": flow.Id,
2170 "device-id": f.deviceHandler.device.Id,
2171 "onu-id": onuID,
2172 "intf": Intf,
2173 "err": err,
2174 })
2175 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302176 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002177
Girish Gowdra82c80982021-03-26 16:22:02 -07002178 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
yasin saplibddc2d72022-02-08 13:10:17 +00002179 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002180 return err
2181 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002182 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002183}
2184
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002185//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002186func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002187
Matteo Scandolof16389e2021-05-18 00:47:08 +00002188 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302189 var direction string
2190 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002191
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302192 for _, action := range flows.GetActions(flow) {
2193 if action.Type == flows.OUTPUT {
2194 if out := action.GetOutput(); out != nil {
2195 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002196 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302197 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002198 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002199 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002200 }
2201 }
2202 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002203
2204 if flows.HasGroup(flow) {
2205 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002206 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002207 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302208 direction = Upstream
2209 } else {
2210 direction = Downstream
2211 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302212
Girish Gowdracefae192020-03-19 18:14:10 -07002213 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002214 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002215
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002216 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002217}
2218
Esin Karamanae41e2b2019-12-17 18:13:13 +00002219//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2220func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002221 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002222 if ethType, ok := classifierInfo[EthType]; ok {
2223 if ethType.(uint32) == IPv4EthType {
2224 if ipProto, ok := classifierInfo[IPProto]; ok {
2225 if ipProto.(uint32) == IgmpProto {
2226 return true
2227 }
2228 }
2229 }
2230 }
2231 }
2232 return false
2233}
2234
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002235// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002236func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002237 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2238 // The device itself is going to be reset as part of deletion. So nothing to be done.
2239 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2240 return nil
2241 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002242 // Step1 : Fill flowControlBlock
2243 // Step2 : Push the flowControlBlock to ONU channel
2244 // Step3 : Wait on response channel for response
2245 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002246 startTime := time.Now()
2247 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002248 errChan := make(chan error)
2249 flowCb := flowControlBlock{
2250 ctx: ctx,
2251 addFlow: addFlow,
2252 flow: flow,
2253 flowMetadata: flowMetadata,
2254 errChan: &errChan,
2255 }
2256 inPort, outPort := getPorts(flow)
2257 var onuID uint32
2258 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002259 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002260 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002261 if f.flowHandlerRoutineActive[onuID] {
2262 // inPort or outPort is InvalidPort for trap-from-nni flows.
2263 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2264 // Send the flowCb on the ONU flow channel
2265 f.incomingFlows[onuID] <- flowCb
2266 // Wait on the channel for flow handlers return value
2267 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002268 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002269 return err
2270 }
2271 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2272 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002273}
2274
2275// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2276// 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 -07002277func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002278 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002279 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002280 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002281 // block on the channel to receive an incoming flow
2282 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002283 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002284 if flowCb.addFlow {
2285 logger.Info(flowCb.ctx, "adding-flow-start")
2286 startTime := time.Now()
2287 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2288 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2289 // Pass the return value over the return channel
2290 *flowCb.errChan <- err
2291 } else {
2292 logger.Info(flowCb.ctx, "removing-flow-start")
2293 startTime := time.Now()
2294 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2295 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2296 // Pass the return value over the return channel
2297 *flowCb.errChan <- err
2298 }
2299 case <-stopHandler:
2300 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2301 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002302 }
2303 }
2304}
2305
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002306// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002307func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002308 for i, v := range f.stopFlowHandlerRoutine {
2309 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002310 select {
2311 case v <- true:
2312 case <-time.After(time.Second * 5):
2313 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2314 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002315 }
2316 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002317 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002318 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2319}
2320
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002321// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302322// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002323func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002324 classifierInfo := make(map[string]interface{})
2325 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002326 var UsMeterID uint32
2327 var DsMeterID uint32
2328
Neha Sharma96b7bf22020-06-15 10:37:32 +00002329 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302330 log.Fields{
2331 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002332 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002333 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002334
Neha Sharma96b7bf22020-06-15 10:37:32 +00002335 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002336 if err != nil {
2337 // Error logging is already done in the called function
2338 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002339 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302340 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002341
Esin Karamanccb714b2019-11-29 15:02:06 +00002342 if flows.HasGroup(flow) {
2343 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002344 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002345 }
2346
manikkaraj k17652a72019-05-06 09:06:36 -04002347 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002348 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002349 if err != nil {
2350 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002351 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002352 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002353
Neha Sharma96b7bf22020-06-15 10:37:32 +00002354 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302355 log.Fields{
2356 "classifierinfo_inport": classifierInfo[InPort],
2357 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002358 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002359
Humera Kouser94d7a842019-08-25 19:04:32 -04002360 if ethType, ok := classifierInfo[EthType]; ok {
2361 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002362 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002363 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002364 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002365 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002366 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002367 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2368 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2369 }
2370 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002371 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002372 if ipProto, ok := classifierInfo[IPProto]; ok {
2373 if ipProto.(uint32) == IPProtoDhcp {
2374 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302375 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002376 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002377 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002378 }
2379 }
2380 }
2381 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002382 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002383 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002384 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002385 }
A R Karthick1f85b802019-10-11 05:06:05 +00002386
yasin saplibddc2d72022-02-08 13:10:17 +00002387 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002388
Girish Gowdra6071f382021-12-14 12:52:04 +05302389 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002390 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302391 return olterrors.NewErrNotFound("tpid-for-flow",
2392 log.Fields{
2393 "flow": flow,
2394 "intf-id": IntfID,
2395 "onu-id": onuID,
2396 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002397 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002398 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302399 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302400 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302401 "intf-id": intfID,
2402 "onu-id": onuID,
2403 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002404 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002405 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002406 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302407 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2408 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2409 return err
2410 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002411 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002412 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302414 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2415 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2416 return err
2417 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002418 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302419 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002420}
Girish Gowdra3d633032019-12-10 16:37:05 +05302421
Esin Karamanccb714b2019-11-29 15:02:06 +00002422// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002423func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302424 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302426 "classifier-info": classifierInfo,
2427 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002428
Esin Karaman65409d82020-03-18 10:58:18 +00002429 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002430 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002431 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002432 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002433
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002434 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002435
David K. Bainbridge794735f2020-02-11 21:01:37 -08002436 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002437
yasin saplibddc2d72022-02-08 13:10:17 +00002438 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002439 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002440 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002441 return nil
yasin saplid0566272021-12-21 09:10:30 +00002442 } else if err != nil {
2443 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2444 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2445 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002446 }
yasin saplid0566272021-12-21 09:10:30 +00002447
David K. Bainbridge794735f2020-02-11 21:01:37 -08002448 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2449 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002450 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002451 }
2452 groupID := actionInfo[GroupID].(uint32)
2453 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002454 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002455 FlowType: Multicast,
2456 NetworkIntfId: int32(networkInterfaceID),
2457 GroupId: groupID,
2458 Classifier: classifierProto,
2459 Priority: int32(flow.Priority),
2460 Cookie: flow.Cookie}
2461
Kent Hagermane6ff1012020-07-14 15:07:53 -04002462 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002463 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002464 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002465 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002466 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002467 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002468 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002469 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002470 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002471 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002472 //cached group can be removed now
2473 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002474 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002475 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002476 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002477
David K. Bainbridge794735f2020-02-11 21:01:37 -08002478 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002479}
2480
Esin Karaman65409d82020-03-18 10:58:18 +00002481//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2482func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2483 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002484 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002485 if err != nil {
2486 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2487 }
2488 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002489 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002490
2491 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2492 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002493}
2494
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002495//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002496func (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 -07002497
Neha Sharma96b7bf22020-06-15 10:37:32 +00002498 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302499 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002500 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302501 log.Fields{
2502 "intf-id": intfID,
2503 "onu-id": onuID,
2504 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002505 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302506 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002507 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002508
yasin saplibddc2d72022-02-08 13:10:17 +00002509 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002510 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002511 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002512 UniId: uniID,
2513 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002514 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002515 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002516 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002517
2518 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2519 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302520 return olterrors.NewErrCommunication("send-techprofile-download-request",
2521 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002522 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302523 "to-adapter": onuDev.deviceType,
2524 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002525 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002526 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002527 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302528 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302529}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002530
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002531//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302532func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002533 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002534
2535 if packetIn.IntfType == "pon" {
2536 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002537 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002538 onuID, uniID := packetIn.OnuId, packetIn.UniId
2539 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 +00002540
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002541 if packetIn.PortNo != 0 {
2542 logicalPortNum = packetIn.PortNo
2543 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002544 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002545 }
2546 // 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 +00002547 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002548 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002549 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002550 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002551
2552 if logger.V(log.DebugLevel) {
2553 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2554 log.Fields{
2555 "logical-port-num": logicalPortNum,
2556 "intf-type": packetIn.IntfType,
2557 "packet": hex.EncodeToString(packetIn.Pkt),
2558 })
2559 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002560 return logicalPortNum, nil
2561}
2562
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002563//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002564func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002565 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002566
2567 ctag, priority, err := getCTagFromPacket(ctx, packet)
2568 if err != nil {
2569 return 0, err
2570 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302571
Esin Karaman7fb80c22020-07-16 14:23:33 +00002572 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002573 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002574 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002575 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002576 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302577 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002578 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302579 log.Fields{
2580 "pktinkey": pktInkey,
2581 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002582
2583 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002584 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302585 //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 +00002586 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302587 if err == nil {
2588 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002589 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302590 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002591 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002592 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302593 log.Fields{
2594 "pktinkey": pktInkey,
2595 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302596 return gemPortID, nil
2597 }
2598 }
Shrey Baid26912972020-04-16 21:02:31 +05302599 return uint32(0), olterrors.NewErrNotFound("gem-port",
2600 log.Fields{
2601 "pktinkey": pktInkey,
2602 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002603
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002604}
2605
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002606func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2607 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002608 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002609 classifier[PacketTagType] = DoubleTag
2610 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002611 /* We manage flowId resource pool on per PON port basis.
2612 Since this situation is tricky, as a hack, we pass the NNI port
2613 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002614 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 on NNI port, use onu_id as -1 (invalid)
2616 ****************** CAVEAT *******************
2617 This logic works if the NNI Port Id falls within the same valid
2618 range of PON Port Ids. If this doesn't work for some OLT Vendor
2619 we need to have a re-look at this.
2620 *********************************************
2621 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002622 onuID := -1
2623 uniID := -1
2624 gemPortID := -1
2625 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002626 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302627 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302628 return olterrors.NewErrNotFound("nni-intreface-id",
2629 log.Fields{
2630 "classifier": classifier,
2631 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002632 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302633 }
2634
yasin saplibddc2d72022-02-08 13:10:17 +00002635 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002636 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002638 return nil
yasin saplid0566272021-12-21 09:10:30 +00002639 } else if err != nil {
2640 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2641 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2642 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002643 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002644
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002645 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2646 log.Fields{
2647 "classifier": classifier,
2648 "action": action,
2649 "flowId": logicalFlow.Id,
2650 "intf-id": networkInterfaceID})
2651
David K. Bainbridge794735f2020-02-11 21:01:37 -08002652 classifierProto, err := makeOpenOltClassifierField(classifier)
2653 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002654 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002655 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002656 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002657 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002658 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002659 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002660 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002661 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002662 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2663 OnuId: int32(onuID), // OnuId not required
2664 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002665 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002666 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002667 AllocId: int32(allocID), // AllocId not used
2668 NetworkIntfId: int32(networkInterfaceID),
2669 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 Classifier: classifierProto,
2671 Action: actionProto,
2672 Priority: int32(logicalFlow.Priority),
2673 Cookie: logicalFlow.Cookie,
2674 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002675 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002676 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002677 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002678 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002679 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002680}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002681
Esin Karamanae41e2b2019-12-17 18:13:13 +00002682//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2683func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2684 var packetType string
2685 ovid, ivid := false, false
2686 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2687 vid := vlanID & VlanvIDMask
2688 if vid != ReservedVlan {
2689 ovid = true
2690 }
2691 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002692
2693 // The classifierInfo[Metadata] is set for the following flows
2694 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2695 // - Mcast flow that points to a group in the action/treatment
2696 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2697 // - inner vid for a double tagged packet in the datapath flow
2698 // - outer vid for a single tagged packet in the datapath flow
2699 // - inner vid in the mcast flow that points to a group
2700
2701 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2702 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2703 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2704 // it is to be used with caution elsewhere as it could result in wrong packetType to be returned to the caller.
Esin Karamanae41e2b2019-12-17 18:13:13 +00002705 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2706 vid := uint32(metadata)
2707 if vid != ReservedVlan {
2708 ivid = true
2709 }
2710 }
2711 if ovid && ivid {
2712 packetType = DoubleTag
2713 } else if !ovid && !ivid {
2714 packetType = Untagged
2715 } else {
2716 packetType = SingleTag
2717 }
2718 return packetType
2719}
2720
2721//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002722func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002723 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002724 action := make(map[string]interface{})
2725 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2726 action[TrapToHost] = true
2727 /* We manage flowId resource pool on per PON port basis.
2728 Since this situation is tricky, as a hack, we pass the NNI port
2729 index (network_intf_id) as PON port Index for the flowId resource
2730 pool. Also, there is no ONU Id available for trapping packets
2731 on NNI port, use onu_id as -1 (invalid)
2732 ****************** CAVEAT *******************
2733 This logic works if the NNI Port Id falls within the same valid
2734 range of PON Port Ids. If this doesn't work for some OLT Vendor
2735 we need to have a re-look at this.
2736 *********************************************
2737 */
2738 onuID := -1
2739 uniID := -1
2740 gemPortID := -1
2741 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002742 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002743 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302744 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002745 "classifier": classifier,
2746 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002747 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002748 }
yasin saplibddc2d72022-02-08 13:10:17 +00002749 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002750 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002751 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002752 return nil
yasin saplid0566272021-12-21 09:10:30 +00002753 } else if err != nil {
2754 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2755 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2756 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002757 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002758
David K. Bainbridge794735f2020-02-11 21:01:37 -08002759 classifierProto, err := makeOpenOltClassifierField(classifier)
2760 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002761 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002762 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002763 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002764 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002765 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002766 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002767 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002768 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002769 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2770 OnuId: int32(onuID), // OnuId not required
2771 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002772 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002773 FlowType: Downstream,
2774 AllocId: int32(allocID), // AllocId not used
2775 NetworkIntfId: int32(networkInterfaceID),
2776 GemportId: int32(gemPortID), // GemportId not used
2777 Classifier: classifierProto,
2778 Action: actionProto,
2779 Priority: int32(logicalFlow.Priority),
2780 Cookie: logicalFlow.Cookie,
2781 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002783 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002785 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002786
David K. Bainbridge794735f2020-02-11 21:01:37 -08002787 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002788}
2789
salmansiddiqui7ac62132019-08-22 03:58:50 +00002790func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2791 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302792 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002793 }
2794 if Dir == tp_pb.Direction_UPSTREAM {
2795 return "upstream", nil
2796 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2797 return "downstream", nil
2798 }
2799 return "", nil
2800}
2801
Kent Hagermane6ff1012020-07-14 15:07:53 -04002802// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302803func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002804 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002805 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002806 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002807 intfID := args[IntfID]
2808 onuID := args[OnuID]
2809 uniID := args[UniID]
2810 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002811 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002812 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002813 gemToAes := make(map[uint32]bool)
2814
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002815 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002816 var direction = tp_pb.Direction_UPSTREAM
2817 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002818 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002819 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002820 attributes = TpInst.UpstreamGemPortAttributeList
2821 } else {
2822 attributes = TpInst.DownstreamGemPortAttributeList
2823 direction = tp_pb.Direction_DOWNSTREAM
2824 }
2825 default:
2826 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002827 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002828 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002829
2830 if len(gemPorts) == 1 {
2831 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002832 gemPortID = gemPorts[0]
2833 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002834 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2835 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002836 pBitMap := attributes[idx].PbitMap
2837 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2838 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2839 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002840 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002841 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2842 if pbitSet == pbit1 {
2843 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2844 pbitToGem[pcp] = gemID
2845 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002846 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002847 }
2848 }
2849 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002850 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2851 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2852 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002853 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002854 }
2855
Gamze Abaka7650be62021-02-26 10:50:36 +00002856 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2857 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2858
salmansiddiqui7ac62132019-08-22 03:58:50 +00002859 if ipProto, ok := classifierInfo[IPProto]; ok {
2860 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002861 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002862 "tp-id": tpID,
2863 "alloc-id": allocID,
2864 "intf-id": intfID,
2865 "onu-id": onuID,
2866 "uni-id": uniID,
2867 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002868 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002869 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002870 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002871 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})
2872 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002873 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002874 }
2875
Girish Gowdra32625212020-04-29 11:26:35 -07002876 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002877 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302878 log.Fields{
2879 "intf-id": intfID,
2880 "onu-id": onuID,
2881 "uni-id": uniID,
2882 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002883 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002884 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002885 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})
2886 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002887 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002888 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002890 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002891 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002892 }
2893 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002894 if ethType.(uint32) == EapEthType {
2895 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002896 "intf-id": intfID,
2897 "onu-id": onuID,
2898 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002899 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002900 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002901 var vlanID uint32
2902 if val, ok := classifierInfo[VlanVid]; ok {
2903 vlanID = (val.(uint32)) & VlanvIDMask
2904 } else {
2905 vlanID = DefaultMgmtVlan
2906 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002907 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002908 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002909 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})
2910 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002911 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002912 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002913 } else if ethType.(uint32) == PPPoEDEthType {
2914 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2915 "tp-id": tpID,
2916 "alloc-id": allocID,
2917 "intf-id": intfID,
2918 "onu-id": onuID,
2919 "uni-id": uniID,
2920 })
2921 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002922 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002923 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002924 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})
2925 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002926 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002927 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002929 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002930 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002931 "intf-id": intfID,
2932 "onu-id": onuID,
2933 "uni-id": uniID,
2934 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002935 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002936 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002937 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002938 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})
2939 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002940 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002942 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002943 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002944 "intf-id": intfID,
2945 "onu-id": onuID,
2946 "uni-id": uniID,
2947 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002948 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002949 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002950 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002951 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})
2952 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002953 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002954 }
2955 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002956 return olterrors.NewErrInvalidValue(log.Fields{
2957 "intf-id": intfID,
2958 "onu-id": onuID,
2959 "uni-id": uniID,
2960 "classifier": classifierInfo,
2961 "action": actionInfo,
2962 "flow": flow},
2963 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002964 }
2965 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002966 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002967 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002968 logger.Warn(ctx, err)
2969 }
2970 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002971 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002972}
2973
Gamze Abakacb0e6772021-06-10 08:32:12 +00002974func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002975 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2976 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2977 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 +05302978 for i := 0; i < len(tpInstances); i++ {
2979 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002980 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002981 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002982 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002983 log.Fields{
2984 "device-id": f.deviceHandler.device.Id,
2985 "intfID": sq.intfID,
2986 "onuID": sq.onuID,
2987 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002988 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002989 })
2990 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302991 }
2992 }
2993 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002994 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002995}
2996
Neha Sharma96b7bf22020-06-15 10:37:32 +00002997func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002998 for _, field := range flows.GetOfbFields(flow) {
2999 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003000 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003001 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003002 } else if field.Type == flows.ETH_DST {
3003 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003004 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
3005 } else if field.Type == flows.ETH_SRC {
3006 classifierInfo[EthSrc] = field.GetEthSrc()
3007 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003008 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003011 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003012 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003014 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303015 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3016 if field.GetVlanVid() != ReservedVlan {
3017 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3018 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3019 }
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003026 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003029 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003032 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003033 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003035 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003036 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003038 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003039 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003040 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003041 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003042 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003043 return
3044 }
3045 }
3046}
3047
Neha Sharma96b7bf22020-06-15 10:37:32 +00003048func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003049 for _, action := range flows.GetActions(flow) {
3050 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003052 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003053 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003054 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003055 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003056 }
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003059 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003060 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 if out := action.GetPush(); out != nil {
3062 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003063 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003064 } else {
3065 actionInfo[PushVlan] = true
3066 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303068 log.Fields{
3069 "push-tpid": actionInfo[TPID].(uint32),
3070 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 }
3072 }
Scott Baker355d1742019-10-24 10:57:52 -07003073 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003074 if out := action.GetSetField(); out != nil {
3075 if field := out.GetField(); field != nil {
3076 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003077 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3080 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 }
3082 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003083 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003085 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003086 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003087 }
3088 }
3089 return nil
3090}
3091
Neha Sharma96b7bf22020-06-15 10:37:32 +00003092func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003093 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003094 fieldtype := ofbField.GetType()
3095 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003096 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3097 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003098 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003099 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003101 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003102 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3103 pcp := ofbField.GetVlanPcp()
3104 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003105 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003106 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003107 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003108 }
3109 }
3110}
3111
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003113 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003115 } else {
3116 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003118 }
3119}
3120
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003122 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003123 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003125 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003126 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003128 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303129 log.Fields{
3130 "newinport": classifierInfo[InPort].(uint32),
3131 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003132 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303133 return olterrors.NewErrNotFound("child-in-port",
3134 log.Fields{
3135 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3136 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003137 }
3138 }
3139 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003140 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003141 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003142 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003143 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003144 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003145 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303146 log.Fields{
3147 "newoutport": actionInfo[Output].(uint32),
3148 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303150 return olterrors.NewErrNotFound("out-port",
3151 log.Fields{
3152 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3153 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003154 }
3155 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003156 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003157 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003158 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003159 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303160 log.Fields{
3161 "newinport": actionInfo[Output].(uint32),
3162 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303164 return olterrors.NewErrNotFound("nni-port",
3165 log.Fields{
3166 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3167 "in-port": classifierInfo[InPort].(uint32),
3168 "out-port": actionInfo[Output].(uint32),
3169 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003170 }
3171 }
3172 }
3173 return nil
3174}
Gamze Abakafee36392019-10-03 11:17:24 +00003175
Neha Sharma96b7bf22020-06-15 10:37:32 +00003176func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003177 /* Metadata 8 bytes:
3178 Most Significant 2 Bytes = Inner VLAN
3179 Next 2 Bytes = Tech Profile ID(TPID)
3180 Least Significant 4 Bytes = Port ID
3181 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3182 subscriber related flows.
3183 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003185 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003186 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003187 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003188 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003189 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003190}
3191
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003192func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003193 for _, sliceElement := range slice {
3194 if sliceElement == item {
3195 return slice
3196 }
3197 }
3198 return append(slice, item)
3199}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303200
yasin saplie87d4bd2021-12-06 09:04:03 +00003201func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3202 for _, sliceElement := range slice {
3203 if sliceElement == item {
3204 return slice
3205 }
3206 }
3207 return append(slice, item)
3208}
3209
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303210// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303212
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003213 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303214 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003215 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003216 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003217 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003218 log.Fields{
3219 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003220 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003221 return uint32(0), err
3222 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003223 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303224 return intfID, nil
3225 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003226 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003227 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003228 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003229 log.Fields{
3230 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003231 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003232 return uint32(0), err
3233 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003234 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303235 return intfID, nil
3236 }
3237 return uint32(0), nil
3238}
3239
3240// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003241func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3242 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3243 if err != nil {
3244 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3245 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3246 return
3247 }
3248 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003249
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003250 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003251 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003252 f.packetInGemPortLock.RUnlock()
3253
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303254 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003255 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 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 +05303257 log.Fields{
3258 "pktinkey": pktInkey,
3259 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003260 return
3261 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303262 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003263 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003264 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003265 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003266
npujarec5762e2020-01-01 14:08:48 +05303267 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003268 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 +05303269 log.Fields{
3270 "pktinkey": pktInkey,
3271 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303272}
3273
Esin Karaman7fb80c22020-07-16 14:23:33 +00003274//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3275func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3276 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003277 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003278 return 0, 0, errors.New("invalid packet length")
3279 }
3280 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3281 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3282
3283 var index int8
3284 if outerEthType == 0x8100 {
3285 if innerEthType == 0x8100 {
3286 // q-in-q 802.1ad or 802.1q double tagged packet.
3287 // get the inner vlanId
3288 index = 18
3289 } else {
3290 index = 14
3291 }
3292 priority := (packet[index] >> 5) & 0x7
3293 //13 bits composes vlanId value
3294 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3295 return vlan, priority, nil
3296 }
3297 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3298 return 0, 0, nil
3299}
3300
Girish Gowdra9602eb42020-09-09 15:50:39 -07003301//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3302// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003303func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003304 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003305 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3306 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003307 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003308 "flow-id": flow.Id,
3309 "device-id": f.deviceHandler.device.Id})
3310 // Remove from device
3311 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3312 // DKB
3313 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3314 log.Fields{
3315 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003316 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003317 return err
3318 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003319
3320 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003321}
3322
khenaidoodc2116e2021-10-19 17:33:19 -04003323func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003324 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003325 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003326 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003327 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003328 }
3329
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003330 switch tpInst := tpInst.(type) {
3331 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003332 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003333 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003334 DeviceId: onuDeviceID,
3335 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003336 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003337 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003338 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003339 case *tp_pb.EponTechProfileInstance:
3340 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003341 DeviceId: onuDeviceID,
3342 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003343 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003344 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003345 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003346 default:
3347 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003348 }
khenaidoodc2116e2021-10-19 17:33:19 -04003349 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003350 DeviceId: onuDeviceID,
3351 UniId: uniID,
3352 TpInstancePath: tpPath,
3353 TechTpInstance: nil,
3354 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003355}
3356
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003357// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3358func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3359
3360 intfID := sq.intfID
3361 onuID := sq.onuID
3362 uniID := sq.uniID
3363 tpID := sq.tpID
3364
3365 var reverseDirection string
3366 if sq.direction == tp_pb.Direction_UPSTREAM {
3367 reverseDirection = "downstream"
3368 } else {
3369 reverseDirection = "upstream"
3370 }
3371
3372 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003373 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003374 return
3375 }
3376
3377 // revert-delete tech-profile instance and delete tech profile id for onu
3378 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})
3379 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3380 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003381 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003382
3383 // free gem/alloc
3384 switch techprofileInst := sq.tpInst.(type) {
3385 case *tp_pb.TechProfileInstance:
3386 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003387 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003388 }
yasin saplibddc2d72022-02-08 13:10:17 +00003389 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003390 }
3391}
3392
3393// revertSchduler is called when CreateQueues request fails
3394func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3395 // revert scheduler
3396 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})
3397 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3398 IntfId: sq.intfID, OnuId: sq.onuID,
3399 UniId: sq.uniID, PortNo: sq.uniPort,
3400 TrafficScheds: TrafficSched})
3401}
Girish Gowdra6071f382021-12-14 12:52:04 +05303402
3403// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3404func (f *OpenOltFlowMgr) validateMeter(ctx context.Context, direction string, meterID uint32, intfID uint32, onuID uint32, uniID uint32, tpID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00003405 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303406 if err != nil {
3407 return olterrors.NewErrNotFound("meter",
3408 log.Fields{"intf-id": intfID,
3409 "onu-id": onuID,
3410 "uni-id": uniID,
3411 "device-id": f.deviceHandler.device.Id}, err)
3412 }
3413
3414 if meterInfo != nil {
3415 // If RefCnt become 0 clear the meter information from the DB.
3416 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003417 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303418 return err
3419 }
3420 } else if meterInfo.MeterID != meterID {
3421 logger.Errorw(ctx, "meter-mismatch-for-direction",
3422 log.Fields{"direction": direction,
3423 "kv-store-meter-id": meterInfo.MeterID,
3424 "meter-id-in-flow": meterID,
3425 "device-id": f.deviceHandler.device.Id})
3426 return olterrors.NewErrInvalidValue(log.Fields{
3427 "unsupported": "meter-id",
3428 "kv-store-meter-id": meterInfo.MeterID,
3429 "meter-id-in-flow": meterID,
3430 "device-id": f.deviceHandler.device.Id}, nil)
3431 }
3432 }
3433 return nil
3434}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003435
3436func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3437 /* After we successfully remove the scheduler configuration on the OLT device,
3438 * delete the meter id on the KV store.
3439 */
yasin saplibddc2d72022-02-08 13:10:17 +00003440 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003441 if err != nil {
3442 return olterrors.NewErrAdapter("unable-to-remove-meter",
3443 log.Fields{
3444 "onu": sq.onuID,
3445 "device-id": f.deviceHandler.device.Id,
3446 "intf-id": sq.intfID,
3447 "onu-id": sq.onuID,
3448 "uni-id": sq.uniID,
3449 "uni-port": sq.uniPort}, err)
3450 }
3451 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3452 log.Fields{
3453 "dir": direction,
3454 "device-id": f.deviceHandler.device.Id,
3455 "intf-id": sq.intfID,
3456 "onu-id": sq.onuID,
3457 "uni-id": sq.uniID,
3458 "uni-port": sq.uniPort})
3459 return err
3460}