blob: 3d5b490fe511cad5aad10aa4cc88b1081f04058c [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 // Ignore Downlink trap flow given by core, cannot do anything with this flow */
1021 if vlan, exists := downlinkClassifier[VlanVid]; exists {
1022 if vlan.(uint32) == (uint32(ofp.OfpVlanId_OFPVID_PRESENT) | 4000) { //private VLAN given by core
David K. Bainbridge82efc492019-09-04 09:57:11 -07001023 if metadata, exists := downlinkClassifier[Metadata]; exists { // inport is filled in metadata by core
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001024 if uint32(metadata.(uint64)) == plt.MkUniPortNum(ctx, flowContext.intfID, flowContext.onuID, flowContext.uniID) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001025 logger.Infow(ctx, "ignoring-dl-trap-device-flow-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301026 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001027 "flow": flowContext.logicalFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301028 "device-id": f.deviceHandler.device.Id,
Gamze Abaka7650be62021-02-26 10:50:36 +00001029 "onu-id": flowContext.onuID,
1030 "intf-id": flowContext.intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001031 return nil
Manikkaraj kb1d51442019-07-23 10:41:02 -04001032 }
1033 }
1034 }
Manikkaraj k884c1242019-04-11 16:26:42 +05301035 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04001036
Girish Gowdraffa52e52022-02-16 15:48:10 -08001037 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1038 // The matched vlan is the one that is getting popped.
1039 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1040 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1041 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1042 if ok {
1043 downlinkAction[VlanVid] = dlClVid & 0xfff
1044 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301045 }
1046
Gamze Abaka7650be62021-02-26 10:50:36 +00001047 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301048}
1049
Gamze Abaka7650be62021-02-26 10:50:36 +00001050func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001051
Gamze Abaka7650be62021-02-26 10:50:36 +00001052 intfID := flowContext.intfID
1053 onuID := flowContext.onuID
1054 uniID := flowContext.uniID
1055 classifier := flowContext.classifier
1056 action := flowContext.action
1057 allocID := flowContext.allocID
1058 gemPortID := flowContext.gemPortID
1059 tpID := flowContext.tpID
1060 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001061 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301062 log.Fields{
1063 "intf-id": intfID,
1064 "onu-id": onuID,
1065 "uni-id": uniID,
1066 "device-id": f.deviceHandler.device.Id,
1067 "classifier": classifier,
1068 "action": action,
1069 "direction": direction,
1070 "alloc-id": allocID,
1071 "gemport-id": gemPortID,
1072 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001073
yasin saplibddc2d72022-02-08 13:10:17 +00001074 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001075 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001076 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301077 log.Fields{
1078 "device-id": f.deviceHandler.device.Id,
1079 "intf-id": intfID,
1080 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001081 return nil
yasin saplid0566272021-12-21 09:10:30 +00001082 } else if err != nil {
1083 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1084 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1085 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301086 }
yasin saplid0566272021-12-21 09:10:30 +00001087
David K. Bainbridge794735f2020-02-11 21:01:37 -08001088 classifierProto, err := makeOpenOltClassifierField(classifier)
1089 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301090 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301091 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "classifier": *classifierProto,
1095 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001096 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301098 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301099 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001100 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301101 log.Fields{
1102 "action": *actionProto,
1103 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001104 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301105 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301106 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001107 log.Fields{
1108 "classifier": classifier,
1109 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301110 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301112 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001113
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001114 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001115 OnuId: int32(onuID),
1116 UniId: int32(uniID),
1117 FlowId: logicalFlow.Id,
1118 FlowType: direction,
1119 AllocId: int32(allocID),
1120 NetworkIntfId: int32(networkIntfID),
1121 GemportId: int32(gemPortID),
1122 Classifier: classifierProto,
1123 Action: actionProto,
1124 Priority: int32(logicalFlow.Priority),
1125 Cookie: logicalFlow.Cookie,
1126 PortNo: flowContext.portNo,
1127 TechProfileId: tpID,
1128 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1129 PbitToGemport: flowContext.pbitToGem,
1130 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001131 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001132 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001133 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301134 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001135 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301136 log.Fields{"direction": direction,
1137 "device-id": f.deviceHandler.device.Id,
1138 "flow": flow,
1139 "intf-id": intfID,
1140 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001141
David K. Bainbridge794735f2020-02-11 21:01:37 -08001142 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301143}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001144
Gamze Abaka7650be62021-02-26 10:50:36 +00001145func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1146
1147 intfID := flowContext.intfID
1148 onuID := flowContext.onuID
1149 uniID := flowContext.uniID
1150 logicalFlow := flowContext.logicalFlow
1151 classifier := flowContext.classifier
1152 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301153
Neha Sharma96b7bf22020-06-15 10:37:32 +00001154 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301155 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301156 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001157 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301158 "action": action,
1159 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001160 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301161 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301162
1163 // Clear the action map
1164 for k := range action {
1165 delete(action, k)
1166 }
1167
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001168 action[TrapToHost] = true
1169 classifier[UDPSrc] = uint32(68)
1170 classifier[UDPDst] = uint32(67)
1171 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301172
yasin saplibddc2d72022-02-08 13:10:17 +00001173 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001174 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001175 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301176 log.Fields{
1177 "device-id": f.deviceHandler.device.Id,
1178 "intf-id": intfID,
1179 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001180 return nil
yasin saplid0566272021-12-21 09:10:30 +00001181 } else if err != nil {
1182 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1183 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1184 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301185 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301186
Neha Sharma96b7bf22020-06-15 10:37:32 +00001187 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301188 log.Fields{
1189 "ul_classifier": classifier,
1190 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001191 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301192 "intf-id": intfID,
1193 "onu-id": onuID,
1194 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301195
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 classifierProto, err := makeOpenOltClassifierField(classifier)
1197 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301198 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001201 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001202 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301203 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301204 }
1205
David K. Bainbridge794735f2020-02-11 21:01:37 -08001206 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001207 OnuId: int32(onuID),
1208 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001209 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001210 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001211 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001212 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001213 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301214 Classifier: classifierProto,
1215 Action: actionProto,
1216 Priority: int32(logicalFlow.Priority),
1217 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001218 PortNo: flowContext.portNo,
1219 TechProfileId: flowContext.tpID,
1220 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1221 PbitToGemport: flowContext.pbitToGem,
1222 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001223 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001224 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001225 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001226 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001227 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301228 log.Fields{
1229 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001230 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301231 "intf-id": intfID,
1232 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301233
David K. Bainbridge794735f2020-02-11 21:01:37 -08001234 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301235}
1236
Esin Karamanae41e2b2019-12-17 18:13:13 +00001237//addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001238func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1239 delete(flowContext.classifier, VlanVid)
1240 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001241}
1242
1243//addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001244func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
1245
1246 intfID := flowContext.intfID
1247 onuID := flowContext.onuID
1248 uniID := flowContext.uniID
1249 logicalFlow := flowContext.logicalFlow
1250 classifier := flowContext.classifier
1251 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001252
Neha Sharma96b7bf22020-06-15 10:37:32 +00001253 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301255 return olterrors.NewErrNotFound("nni-interface-id",
1256 log.Fields{
1257 "classifier": classifier,
1258 "action": action,
1259 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001260 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001261 }
1262
1263 // Clear the action map
1264 for k := range action {
1265 delete(action, k)
1266 }
1267
1268 action[TrapToHost] = true
1269 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001270
yasin saplibddc2d72022-02-08 13:10:17 +00001271 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001272 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001273 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 return nil
yasin saplid0566272021-12-21 09:10:30 +00001275 } else if err != nil {
1276 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1277 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1278 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001279 }
1280
Neha Sharma96b7bf22020-06-15 10:37:32 +00001281 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301282 log.Fields{
1283 "ul_classifier": classifier,
1284 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001285 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301286 "device-id": f.deviceHandler.device.Id,
1287 "intf-id": intfID,
1288 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001289
David K. Bainbridge794735f2020-02-11 21:01:37 -08001290 classifierProto, err := makeOpenOltClassifierField(classifier)
1291 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301292 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001294 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301295 log.Fields{
1296 "classifier": *classifierProto,
1297 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001298 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001299 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301300 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001301 }
1302
David K. Bainbridge794735f2020-02-11 21:01:37 -08001303 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304 OnuId: int32(onuID),
1305 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001306 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001307 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001308 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001309 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001310 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001311 Classifier: classifierProto,
1312 Action: actionProto,
1313 Priority: int32(logicalFlow.Priority),
1314 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001315 PortNo: flowContext.portNo,
1316 TechProfileId: flowContext.tpID,
1317 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1318 PbitToGemport: flowContext.pbitToGem,
1319 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001320 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001321
David K. Bainbridge794735f2020-02-11 21:01:37 -08001322 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001323 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 -08001324 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001325
David K. Bainbridge794735f2020-02-11 21:01:37 -08001326 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001327}
1328
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001329// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001330func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1331 intfID := flowContext.intfID
1332 onuID := flowContext.onuID
1333 uniID := flowContext.uniID
1334 portNo := flowContext.portNo
1335 allocID := flowContext.allocID
1336 gemPortID := flowContext.gemPortID
1337 logicalFlow := flowContext.logicalFlow
1338 classifier := flowContext.classifier
1339 action := flowContext.action
1340
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001341 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301342 log.Fields{
1343 "intf-id": intfID,
1344 "onu-id": onuID,
1345 "port-no": portNo,
1346 "alloc-id": allocID,
1347 "gemport-id": gemPortID,
1348 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001349 "flow": logicalFlow,
1350 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301351
1352 uplinkClassifier := make(map[string]interface{})
1353 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301354
manikkaraj kbf256be2019-03-25 00:13:48 +05301355 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001356 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001357 uplinkClassifier[PacketTagType] = SingleTag
1358 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001359 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301360 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001361 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001362 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001363 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001364 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301365 "device-id": f.deviceHandler.device.Id,
1366 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001367 "intf-id": intfID,
1368 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001369 return nil
yasin saplid0566272021-12-21 09:10:30 +00001370 } else if err != nil {
1371 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1372 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1373 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301374 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001375 //Add Uplink EthType Flow
1376 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301377 log.Fields{
1378 "ul_classifier": uplinkClassifier,
1379 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001380 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301381 "device-id": f.deviceHandler.device.Id,
1382 "intf-id": intfID,
1383 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301384
David K. Bainbridge794735f2020-02-11 21:01:37 -08001385 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1386 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301387 return olterrors.NewErrInvalidValue(log.Fields{
1388 "classifier": uplinkClassifier,
1389 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301390 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001391 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301392 log.Fields{
1393 "classifier": *classifierProto,
1394 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001395 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001396 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301397 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301398 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001399 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301400 log.Fields{
1401 "action": *actionProto,
1402 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301404 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301405 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001406 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301407 "action": action,
1408 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001409 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301410 }
1411
David K. Bainbridge794735f2020-02-11 21:01:37 -08001412 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001413 OnuId: int32(onuID),
1414 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001415 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001416 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001417 AllocId: int32(allocID),
1418 NetworkIntfId: int32(networkIntfID),
1419 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301420 Classifier: classifierProto,
1421 Action: actionProto,
1422 Priority: int32(logicalFlow.Priority),
1423 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001424 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001425 TechProfileId: flowContext.tpID,
1426 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1427 PbitToGemport: flowContext.pbitToGem,
1428 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001429 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001430 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001431 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001432 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001433 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301434 log.Fields{
1435 "device-id": f.deviceHandler.device.Id,
1436 "onu-id": onuID,
1437 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001438 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301439 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001440
David K. Bainbridge794735f2020-02-11 21:01:37 -08001441 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301442}
1443
David K. Bainbridge794735f2020-02-11 21:01:37 -08001444func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001445 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001446
1447 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1448 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1449 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001450 if vlanID != ReservedVlan {
1451 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001452 classifier.OVid = vid
1453 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301454 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301455 // The classifierInfo[Metadata] carries the vlan that the OLT see when it receives packet from the ONU
David K. Bainbridge82efc492019-09-04 09:57:11 -07001456 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1457 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301458 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1459 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
1460 //is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
1461 // becomes the IVid.
1462 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1463 if vid != ReservedVlan {
1464 classifier.IVid = vid
1465 }
1466 } else {
1467 if vid != ReservedVlan {
1468 classifier.OVid = vid
1469 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001470 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301471 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301472 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001473 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301474 classifier.OPbits = vlanPcp
1475 } else {
1476 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301477 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001478 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1479 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1480 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1481 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001482 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001483 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001484 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1485 classifier.PktTagType = pktTagType
1486
1487 switch pktTagType {
1488 case SingleTag:
1489 case DoubleTag:
1490 case Untagged:
1491 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001492 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301493 }
1494 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001495 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301496}
1497
Gamze Abaka724d0852020-03-18 12:10:24 +00001498func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001499 var actionCmd openoltpb2.ActionCmd
1500 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301501 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001502 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001503 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301504 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001505 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001506 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001507 action.Cmd.RemarkInnerPbits = true
1508 action.IPbits = actionInfo[VlanPcp].(uint32)
1509 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001510 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001511 action.Cmd.TranslateInnerTag = true
1512 action.IVid = actionInfo[VlanVid].(uint32)
1513 }
1514 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001515 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001516 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001517 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301518 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001519 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001520 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001521 action.OPbits = actionInfo[VlanPcp].(uint32)
1522 action.Cmd.RemarkOuterPbits = true
1523 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001524 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001525 action.IVid = classifierInfo[VlanVid].(uint32)
1526 action.Cmd.TranslateInnerTag = true
1527 }
1528 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001529 } else if _, ok := actionInfo[TrapToHost]; ok {
1530 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001531 } else if _, ok := actionInfo[VlanVid]; ok {
1532 // Translate outer vid
1533 action.Cmd.TranslateOuterTag = true
1534 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301535 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301536 // When OLT is transparent to vlans no-action is valid.
1537 /*
1538 else {
1539 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1540 }
1541 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001542 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301543}
1544
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001545// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001546func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001547 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301548}
1549
Gamze Abakafee36392019-10-03 11:17:24 +00001550// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001551// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1552// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1553// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1554// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1555// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1556// because it was observed that if the ONU device was deleted too soon after the flows were
1557// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1558// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1559// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001560func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001561 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001562 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1563
Gamze Abakafee36392019-10-03 11:17:24 +00001564 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001565
1566 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001567 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001568 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001569 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001570 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1571 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1572 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1573 log.Fields{
1574 "tp-id": tpID,
1575 "path": tpPath})
1576 }
1577 switch tpInstance := tpInst.(type) {
1578 case *tp_pb.TechProfileInstance:
1579 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1580 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1581 }
1582 // Force cleanup scheduler/queues -- end
1583
1584 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301585 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001586 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301587 // return err
1588 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001589 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001590 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 +00001591 }
1592 return nil
1593}
1594
1595// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301596func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001597 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001598 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001599 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001600 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301601 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1602 log.Fields{
1603 "tp-id": tpID,
1604 "uni-port-name": uniPortName,
1605 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001606 }
1607 return nil
1608}
1609
David K. Bainbridge794735f2020-02-11 21:01:37 -08001610func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001611
1612 var intfID uint32
1613 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1614 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1615 */
1616 if deviceFlow.AccessIntfId != -1 {
1617 intfID = uint32(deviceFlow.AccessIntfId)
1618 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001619 // We need to log the valid interface ID.
1620 // 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 +00001621 intfID = uint32(deviceFlow.NetworkIntfId)
1622 }
1623
Neha Sharma96b7bf22020-06-15 10:37:32 +00001624 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301625 "flow": *deviceFlow,
1626 "device-id": f.deviceHandler.device.Id,
1627 "intf-id": intfID})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001628 _, err := f.deviceHandler.Client.FlowAdd(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Daniele Rossi22db98e2019-07-11 11:50:00 +00001629
1630 st, _ := status.FromError(err)
1631 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001632 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001633 "err": err,
1634 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301635 "device-id": f.deviceHandler.device.Id,
1636 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001637 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301638 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001639
1640 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001641 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301642 log.Fields{"err": err,
1643 "device-flow": deviceFlow,
1644 "device-id": f.deviceHandler.device.Id,
1645 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001646 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001647 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001648 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301649 log.Fields{
1650 "flow": *deviceFlow,
1651 "device-id": f.deviceHandler.device.Id,
1652 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001653
yasin saplid0566272021-12-21 09:10:30 +00001654 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1655 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1656 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001657 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001658 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001659}
1660
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1662 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301663 log.Fields{
1664 "flow": *deviceFlow,
1665 "device-id": f.deviceHandler.device.Id})
Neha Sharma8f4e4322020-08-06 10:51:53 +00001666 _, err := f.deviceHandler.Client.FlowRemove(log.WithSpanFromContext(context.Background(), ctx), deviceFlow)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001667 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001668 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001669 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301670 log.Fields{
1671 "err": err,
1672 "deviceFlow": deviceFlow,
1673 "device-id": f.deviceHandler.device.Id})
serkant.uluderya245caba2019-09-24 23:15:29 -07001674 //Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001675 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001676 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001677 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
serkant.uluderya245caba2019-09-24 23:15:29 -07001678
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001679 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001680 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001681 "of-flow-id": ofFlowID,
1682 "flow": *deviceFlow,
1683 "device-id": f.deviceHandler.device.Id,
1684 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001685 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301686}
1687
David K. Bainbridge794735f2020-02-11 21:01:37 -08001688func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001689
1690 classifierInfo := make(map[string]interface{})
1691 actionInfo := make(map[string]interface{})
1692
1693 classifierInfo[EthType] = uint32(LldpEthType)
1694 classifierInfo[PacketTagType] = Untagged
1695 actionInfo[TrapToHost] = true
1696
1697 // LLDP flow is installed to trap LLDP packets on the NNI port.
1698 // We manage flow_id resource pool on per PON port basis.
1699 // Since this situation is tricky, as a hack, we pass the NNI port
1700 // index (network_intf_id) as PON port Index for the flow_id resource
1701 // pool. Also, there is no ONU Id available for trapping LLDP packets
1702 // on NNI port, use onu_id as -1 (invalid)
1703 // ****************** CAVEAT *******************
1704 // This logic works if the NNI Port Id falls within the same valid
1705 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1706 // we need to have a re-look at this.
1707 // *********************************************
1708
1709 var onuID = -1
1710 var uniID = -1
1711 var gemPortID = -1
1712
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001713 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001714 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301715 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001716 }
yasin saplibddc2d72022-02-08 13:10:17 +00001717 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001718 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001719 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001720 return nil
yasin saplid0566272021-12-21 09:10:30 +00001721 } else if err != nil {
1722 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1723 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1724 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001725 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001726
David K. Bainbridge794735f2020-02-11 21:01:37 -08001727 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1728 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301729 return olterrors.NewErrInvalidValue(
1730 log.Fields{
1731 "classifier": classifierInfo,
1732 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001733 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001734 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301735 log.Fields{
1736 "classifier": *classifierProto,
1737 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001738 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001739 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301740 return olterrors.NewErrInvalidValue(
1741 log.Fields{
1742 "action": actionInfo,
1743 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001744 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001745 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301746 log.Fields{
1747 "action": *actionProto,
1748 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001749
1750 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1751 OnuId: int32(onuID), // OnuId not required
1752 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001753 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001754 FlowType: Downstream,
1755 NetworkIntfId: int32(networkInterfaceID),
1756 GemportId: int32(gemPortID),
1757 Classifier: classifierProto,
1758 Action: actionProto,
1759 Priority: int32(flow.Priority),
1760 Cookie: flow.Cookie,
1761 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001763 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301764 log.Fields{
1765 "flow": downstreamflow,
1766 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001767 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001768 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301769 log.Fields{
1770 "device-id": f.deviceHandler.device.Id,
1771 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001772 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001773
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301775}
1776
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001777func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1778 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001779}
1780
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001781//getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001782func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001783 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1784 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1785 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001786 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301787 log.Fields{
1788 "intf-id": intfID,
1789 "onu-id": onuID,
1790 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001791 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001792 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301793 return nil, olterrors.NewErrNotFound("onu-child-device",
1794 log.Fields{
1795 "onu-id": onuID,
1796 "intf-id": intfID,
1797 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001798 }
khenaidoo106c61a2021-08-11 18:05:46 -04001799 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 -07001800 //better to ad the device to cache here.
1801 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1802 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "intf-id": intfID,
1806 "onu-id": onuID,
1807 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001808 }
1809
1810 return onuDev.(*OnuDevice), nil
1811}
1812
1813//getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001814func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1815 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301816 log.Fields{
1817 "pon-port": intfID,
1818 "onu-id": onuID,
1819 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001820 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001822 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301823 return nil, olterrors.NewErrNotFound("onu",
1824 log.Fields{
1825 "interface-id": parentPortNo,
1826 "onu-id": onuID,
1827 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001828 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301829 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001830 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301831 log.Fields{
1832 "device-id": f.deviceHandler.device.Id,
1833 "child_device_id": onuDevice.Id,
1834 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301835 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301836}
1837
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1839 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301840 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301842 log.Fields{
1843 "intf-id": intfID,
1844 "onu-id": onuID,
1845 "uni-id": uniID,
1846 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001847 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301848 }
1849
khenaidoodc2116e2021-10-19 17:33:19 -04001850 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001851 DeviceId: onuDev.deviceID,
1852 UniId: uniID,
1853 TpInstancePath: tpPath,
1854 GemPortId: gemPortID,
1855 }
1856 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1857
1858 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301859 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1860 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001861 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1862 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301863 "onu-id": onuDev.deviceID,
1864 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001865 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301866 }
khenaidoo106c61a2021-08-11 18:05:46 -04001867
Neha Sharma96b7bf22020-06-15 10:37:32 +00001868 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301869 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001870 "msg": delGemPortMsg,
1871 "from-adapter": f.deviceHandler.device.Type,
1872 "to-adapter": onuDev.deviceType,
1873 "device-id": f.deviceHandler.device.Id,
1874 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 return nil
1876}
1877
Neha Sharma96b7bf22020-06-15 10:37:32 +00001878func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1879 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301880 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001881 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301882 log.Fields{
1883 "intf-id": intfID,
1884 "onu-id": onuID,
1885 "uni-id": uniID,
1886 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001887 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 }
1889
khenaidoodc2116e2021-10-19 17:33:19 -04001890 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001891 DeviceId: onuDev.deviceID,
1892 UniId: uniID,
1893 TpInstancePath: tpPath,
1894 AllocId: allocID,
1895 }
1896
Neha Sharma96b7bf22020-06-15 10:37:32 +00001897 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301898 log.Fields{
1899 "msg": *delTcontMsg,
1900 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001901
1902 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301903 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1904 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001905 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1906 "to-adapter": onuDev.adapterEndpoint,
1907 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301908 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001909 "device-id": f.deviceHandler.device.Id}, err)
1910
Girish Gowdra6b130582019-11-20 16:45:20 +05301911 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001912 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301913 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001914 "msg": delTcontMsg,
1915 "device-id": f.deviceHandler.device.Id,
1916 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301917 return nil
1918}
1919
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05301920//clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001921// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001922func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Gamze Abaka411ef2f2021-11-22 08:38:08 +00001923 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001924
1925 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001926
Girish Gowdraa482f272021-03-24 23:04:19 -07001927 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001928 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001929 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1930 log.Fields{
1931 "tpPath": tpPath,
1932 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001933
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001934 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001935 if err != nil || techprofileInst == nil {
1936 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1937 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1938 if childDevice == nil {
1939 // happens when subscriber un-provision is immediately followed by child device delete
1940 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1941 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1942 return nil
1943 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001944 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1945 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001946 log.Fields{
1947 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001948 "path": tpPath}, err).Log()
1949 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001950 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001951
1952 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001954 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001955 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1956 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001957 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1958 if err != nil {
1959 return err
1960 }
1961 used := false
1962 for _, id := range flowIDs {
1963 if flowID != id {
1964 used = true
1965 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001966 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001967 }
1968 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001969 for i, flowIDinMap := range flowIDs {
1970 if flowIDinMap == flowID {
1971 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001972 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001973 return err
1974 }
1975 break
1976 }
1977 }
1978 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1979 log.Fields{
1980 "gemport-id": gemPortID,
1981 "usedByFlows": flowIDs,
1982 "currentFlow": flowID,
1983 "device-id": f.deviceHandler.device.Id})
1984 allGemPortsFree = false
1985 }
1986 }
1987 if !allGemPortsFree {
1988 return nil
1989 }
1990 }
1991
1992 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 -08001993
1994 // 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 +00001995 switch techprofileInst := techprofileInst.(type) {
1996 case *tp_pb.TechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00001997 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08001998 logger.Warn(ctx, err)
1999 }
2000 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2001 logger.Warn(ctx, err)
2002 }
2003
2004 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2005 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00002006 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08002007
yasin saplibddc2d72022-02-08 13:10:17 +00002008 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002009 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2010 log.Fields{
2011 "err": err,
2012 "intf": intfID,
2013 "onu-id": onuID,
2014 "uni-id": uniID,
2015 "device-id": f.deviceHandler.device.Id,
2016 "gemport-id": gemPortID})
2017 }
2018
2019 }
2020 // Remove queues at OLT in upstream and downstream direction
2021 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2022 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2023 logger.Warn(ctx, err)
2024 }
2025 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
2026 if err := f.RemoveQueues(ctx, schedQueue); err != nil {
2027 logger.Warn(ctx, err)
2028 }
2029 }
2030
2031 switch techprofileInst := techprofileInst.(type) {
2032 case *tp_pb.TechProfileInstance:
2033 // 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 +01002034 schedQueue := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2035 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQueue)
2036 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002037 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002038 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002039 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002040 logger.Warn(ctx, err)
2041 }
2042 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002043 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002044 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002045 } else {
2046 // just remove meter reference for the upstream direction for the current pon/onu/uni
2047 // 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
2048 if err := f.removeMeterReference(ctx, "upstream", schedQueue); err != nil {
2049 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002050 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002051 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2052 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002053 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002054 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002055
Girish Gowdraf3728b12022-02-02 21:46:51 -08002056 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
2057 schedQueue.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002058 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002059 if err := f.RemoveScheduler(ctx, schedQueue); err != nil {
2060 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002061 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002062 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002063 case *tp_pb.EponTechProfileInstance:
yasin saplibddc2d72022-02-08 13:10:17 +00002064 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002065 logger.Warn(ctx, err)
2066 }
Girish Gowdraa482f272021-03-24 23:04:19 -07002067 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002068 logger.Warn(ctx, err)
2069 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002070 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002071 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002072 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302073 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002074 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302075 "onu-id": onuID,
2076 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002077 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002078 "alloc-id": techprofileInst.AllocId,
2079 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002080 }
yasin saplibddc2d72022-02-08 13:10:17 +00002081 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002082 default:
2083 logger.Errorw(ctx, "error-unknown-tech",
2084 log.Fields{
2085 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002086 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002087
2088 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2089 switch techprofileInst := techprofileInst.(type) {
2090 case *tp_pb.TechProfileInstance:
2091 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2092 // Delete the gem port on the ONU.
2093 if sendDeleteGemRequest {
2094 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2095 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2096 log.Fields{
2097 "err": err,
2098 "intfID": intfID,
2099 "onu-id": onuID,
2100 "uni-id": uniID,
2101 "device-id": f.deviceHandler.device.Id,
2102 "gemport-id": gemPort.GemportId})
2103 }
yasin saplibddc2d72022-02-08 13:10:17 +00002104 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002105 }
2106 }
2107 }
2108
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302109 return nil
2110}
2111
David K. Bainbridge794735f2020-02-11 21:01:37 -08002112// nolint: gocyclo
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002113func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002114 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302115 log.Fields{
2116 "flowDirection": flowDirection,
2117 "flow": *flow,
2118 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002119
2120 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002121 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002122 }
2123
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302124 var ethType, ipProto, inPort uint32
2125 for _, field := range flows.GetOfbFields(flow) {
2126 if field.Type == flows.IP_PROTO {
2127 ipProto = field.GetIpProto()
2128 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
2129 } else if field.Type == flows.ETH_TYPE {
2130 ethType = field.GetEthType()
2131 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
2132 } else if field.Type == flows.IN_PORT {
2133 inPort = field.GetPort()
2134 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2135 }
2136 }
2137 portType := plt.IntfIDToPortTypeName(inPort)
2138 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2139 (portType == voltha.Port_ETHERNET_NNI) {
2140 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2141 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2142 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2143 // No more processing needed for trap from nni flows.
2144 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302145
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302146 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302147 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002148 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002149 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302150 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002151 onuID := int32(onu)
2152 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002153 tpID, err := getTpIDFromFlow(ctx, flow)
2154 if err != nil {
2155 return olterrors.NewErrNotFound("tp-id",
2156 log.Fields{
2157 "flow": flow,
2158 "intf-id": Intf,
2159 "onu-id": onuID,
2160 "uni-id": uniID,
2161 "device-id": f.deviceHandler.device.Id}, err)
2162 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302163
Neha Sharma96b7bf22020-06-15 10:37:32 +00002164 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302165 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002166 "flow-id": flow.Id,
2167 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302168 "onu-id": onuID,
2169 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302170
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002171 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2172 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002173 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2174 return err
2175 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002176
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002177 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002178 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2179 "flow-id": flow.Id,
2180 "device-id": f.deviceHandler.device.Id,
2181 "onu-id": onuID,
2182 "intf": Intf,
2183 "err": err,
2184 })
2185 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302186 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002187
Girish Gowdra82c80982021-03-26 16:22:02 -07002188 // 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 +00002189 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002190 return err
2191 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002192 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002193}
2194
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002195//RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002196func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002197
Matteo Scandolof16389e2021-05-18 00:47:08 +00002198 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302199 var direction string
2200 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002201
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302202 for _, action := range flows.GetActions(flow) {
2203 if action.Type == flows.OUTPUT {
2204 if out := action.GetOutput(); out != nil {
2205 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002206 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302207 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002208 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002209 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002210 }
2211 }
2212 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002213
2214 if flows.HasGroup(flow) {
2215 direction = Multicast
Girish Gowdrae8f473b2020-10-16 11:07:21 -07002216 return f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002217 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302218 direction = Upstream
2219 } else {
2220 direction = Downstream
2221 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302222
Girish Gowdracefae192020-03-19 18:14:10 -07002223 // Serialize flow removes on a per subscriber basis
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002224 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction)
Girish Gowdracefae192020-03-19 18:14:10 -07002225
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002226 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002227}
2228
Esin Karamanae41e2b2019-12-17 18:13:13 +00002229//isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
2230func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002231 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002232 if ethType, ok := classifierInfo[EthType]; ok {
2233 if ethType.(uint32) == IPv4EthType {
2234 if ipProto, ok := classifierInfo[IPProto]; ok {
2235 if ipProto.(uint32) == IgmpProto {
2236 return true
2237 }
2238 }
2239 }
2240 }
2241 }
2242 return false
2243}
2244
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002245// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002246func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002247 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2248 // The device itself is going to be reset as part of deletion. So nothing to be done.
2249 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2250 return nil
2251 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002252 // Step1 : Fill flowControlBlock
2253 // Step2 : Push the flowControlBlock to ONU channel
2254 // Step3 : Wait on response channel for response
2255 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002256 startTime := time.Now()
2257 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002258 errChan := make(chan error)
2259 flowCb := flowControlBlock{
2260 ctx: ctx,
2261 addFlow: addFlow,
2262 flow: flow,
2263 flowMetadata: flowMetadata,
2264 errChan: &errChan,
2265 }
2266 inPort, outPort := getPorts(flow)
2267 var onuID uint32
2268 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002269 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002270 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002271 if f.flowHandlerRoutineActive[onuID] {
2272 // inPort or outPort is InvalidPort for trap-from-nni flows.
2273 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2274 // Send the flowCb on the ONU flow channel
2275 f.incomingFlows[onuID] <- flowCb
2276 // Wait on the channel for flow handlers return value
2277 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002278 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002279 return err
2280 }
2281 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2282 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002283}
2284
2285// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2286// 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 -07002287func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002288 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002289 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002290 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002291 // block on the channel to receive an incoming flow
2292 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002293 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002294 if flowCb.addFlow {
2295 logger.Info(flowCb.ctx, "adding-flow-start")
2296 startTime := time.Now()
2297 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2298 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2299 // Pass the return value over the return channel
2300 *flowCb.errChan <- err
2301 } else {
2302 logger.Info(flowCb.ctx, "removing-flow-start")
2303 startTime := time.Now()
2304 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2305 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2306 // Pass the return value over the return channel
2307 *flowCb.errChan <- err
2308 }
2309 case <-stopHandler:
2310 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2311 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002312 }
2313 }
2314}
2315
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002316// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002317func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002318 for i, v := range f.stopFlowHandlerRoutine {
2319 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002320 select {
2321 case v <- true:
2322 case <-time.After(time.Second * 5):
2323 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2324 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002325 }
2326 }
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002327 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002328 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2329}
2330
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002331// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302332// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002333func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002334 classifierInfo := make(map[string]interface{})
2335 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002336 var UsMeterID uint32
2337 var DsMeterID uint32
2338
Neha Sharma96b7bf22020-06-15 10:37:32 +00002339 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302340 log.Fields{
2341 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002342 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002343 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002344
Neha Sharma96b7bf22020-06-15 10:37:32 +00002345 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002346 if err != nil {
2347 // Error logging is already done in the called function
2348 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002349 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302350 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002351
Esin Karamanccb714b2019-11-29 15:02:06 +00002352 if flows.HasGroup(flow) {
2353 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002354 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002355 }
2356
manikkaraj k17652a72019-05-06 09:06:36 -04002357 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002358 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002359 if err != nil {
2360 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002361 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002362 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002363
Neha Sharma96b7bf22020-06-15 10:37:32 +00002364 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302365 log.Fields{
2366 "classifierinfo_inport": classifierInfo[InPort],
2367 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002368 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002369
Humera Kouser94d7a842019-08-25 19:04:32 -04002370 if ethType, ok := classifierInfo[EthType]; ok {
2371 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002372 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002373 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002374 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002375 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002376 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002377 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2378 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2379 }
2380 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002381 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002382 if ipProto, ok := classifierInfo[IPProto]; ok {
2383 if ipProto.(uint32) == IPProtoDhcp {
2384 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302385 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002386 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002387 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002388 }
2389 }
2390 }
2391 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002392 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002394 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002395 }
A R Karthick1f85b802019-10-11 05:06:05 +00002396
yasin saplibddc2d72022-02-08 13:10:17 +00002397 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002398
Girish Gowdra6071f382021-12-14 12:52:04 +05302399 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002400 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302401 return olterrors.NewErrNotFound("tpid-for-flow",
2402 log.Fields{
2403 "flow": flow,
2404 "intf-id": IntfID,
2405 "onu-id": onuID,
2406 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002407 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002408 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302409 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302410 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302411 "intf-id": intfID,
2412 "onu-id": onuID,
2413 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002414 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002415 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002416 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302417 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2418 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2419 return err
2420 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002421 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002422 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002423 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302424 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2425 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2426 return err
2427 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002428 }
Girish Gowdra6071f382021-12-14 12:52:04 +05302429 return f.processAddFlow(ctx, intfID, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002430}
Girish Gowdra3d633032019-12-10 16:37:05 +05302431
Esin Karamanccb714b2019-11-29 15:02:06 +00002432// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002433func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302434 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002435 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302436 "classifier-info": classifierInfo,
2437 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002438
Esin Karaman65409d82020-03-18 10:58:18 +00002439 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002440 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002441 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002442 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002443
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002444 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002445
David K. Bainbridge794735f2020-02-11 21:01:37 -08002446 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002447
yasin saplibddc2d72022-02-08 13:10:17 +00002448 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002449 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002450 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002451 return nil
yasin saplid0566272021-12-21 09:10:30 +00002452 } else if err != nil {
2453 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2454 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2455 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002456 }
yasin saplid0566272021-12-21 09:10:30 +00002457
David K. Bainbridge794735f2020-02-11 21:01:37 -08002458 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2459 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002460 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002461 }
2462 groupID := actionInfo[GroupID].(uint32)
2463 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002464 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002465 FlowType: Multicast,
2466 NetworkIntfId: int32(networkInterfaceID),
2467 GroupId: groupID,
2468 Classifier: classifierProto,
2469 Priority: int32(flow.Priority),
2470 Cookie: flow.Cookie}
2471
Kent Hagermane6ff1012020-07-14 15:07:53 -04002472 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002473 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002474 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002475 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002476 //get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002477 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
David K. Bainbridge794735f2020-02-11 21:01:37 -08002478 //calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002479 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002480 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002481 }
Kent Hagermane6ff1012020-07-14 15:07:53 -04002482 //cached group can be removed now
2483 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002484 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002485 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002486 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002487
David K. Bainbridge794735f2020-02-11 21:01:37 -08002488 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002489}
2490
Esin Karaman65409d82020-03-18 10:58:18 +00002491//getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
2492func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2493 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002494 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002495 if err != nil {
2496 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2497 }
2498 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002499 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002500
2501 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2502 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002503}
2504
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002505//sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002506func (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 -07002507
Neha Sharma96b7bf22020-06-15 10:37:32 +00002508 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302509 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002510 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302511 log.Fields{
2512 "intf-id": intfID,
2513 "onu-id": onuID,
2514 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002515 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302516 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002517 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002518
yasin saplibddc2d72022-02-08 13:10:17 +00002519 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002520 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002521 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002522 UniId: uniID,
2523 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002524 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002527
2528 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2529 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302530 return olterrors.NewErrCommunication("send-techprofile-download-request",
2531 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002532 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302533 "to-adapter": onuDev.deviceType,
2534 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002535 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002536 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002537 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
Manikkaraj k884c1242019-04-11 16:26:42 +05302538 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302539}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002540
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002541//GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302542func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002543 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002544
2545 if packetIn.IntfType == "pon" {
2546 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002547 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002548 onuID, uniID := packetIn.OnuId, packetIn.UniId
2549 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 +00002550
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002551 if packetIn.PortNo != 0 {
2552 logicalPortNum = packetIn.PortNo
2553 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002554 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002555 }
2556 // 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 +00002557 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002558 } else if packetIn.IntfType == "nni" {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002559 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002560 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002561
2562 if logger.V(log.DebugLevel) {
2563 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2564 log.Fields{
2565 "logical-port-num": logicalPortNum,
2566 "intf-type": packetIn.IntfType,
2567 "packet": hex.EncodeToString(packetIn.Pkt),
2568 })
2569 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002570 return logicalPortNum, nil
2571}
2572
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002573//GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002574func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002575 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002576
2577 ctag, priority, err := getCTagFromPacket(ctx, packet)
2578 if err != nil {
2579 return 0, err
2580 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302581
Esin Karaman7fb80c22020-07-16 14:23:33 +00002582 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002583 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002584 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002585 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002586 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302587 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002588 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302589 log.Fields{
2590 "pktinkey": pktInkey,
2591 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002592
2593 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002594 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302595 //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 +00002596 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302597 if err == nil {
2598 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002599 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302600 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002601 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002602 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302603 log.Fields{
2604 "pktinkey": pktInkey,
2605 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302606 return gemPortID, nil
2607 }
2608 }
Shrey Baid26912972020-04-16 21:02:31 +05302609 return uint32(0), olterrors.NewErrNotFound("gem-port",
2610 log.Fields{
2611 "pktinkey": pktInkey,
2612 "gem": gemPortID}, err)
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002613
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002614}
2615
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002616func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2617 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002618 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002619 classifier[PacketTagType] = DoubleTag
2620 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002621 /* We manage flowId resource pool on per PON port basis.
2622 Since this situation is tricky, as a hack, we pass the NNI port
2623 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002624 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002625 on NNI port, use onu_id as -1 (invalid)
2626 ****************** CAVEAT *******************
2627 This logic works if the NNI Port Id falls within the same valid
2628 range of PON Port Ids. If this doesn't work for some OLT Vendor
2629 we need to have a re-look at this.
2630 *********************************************
2631 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002632 onuID := -1
2633 uniID := -1
2634 gemPortID := -1
2635 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002636 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302637 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302638 return olterrors.NewErrNotFound("nni-intreface-id",
2639 log.Fields{
2640 "classifier": classifier,
2641 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002642 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302643 }
2644
yasin saplibddc2d72022-02-08 13:10:17 +00002645 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002646 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002647 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002648 return nil
yasin saplid0566272021-12-21 09:10:30 +00002649 } else if err != nil {
2650 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2651 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2652 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002653 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002654
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002655 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2656 log.Fields{
2657 "classifier": classifier,
2658 "action": action,
2659 "flowId": logicalFlow.Id,
2660 "intf-id": networkInterfaceID})
2661
David K. Bainbridge794735f2020-02-11 21:01:37 -08002662 classifierProto, err := makeOpenOltClassifierField(classifier)
2663 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002664 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002665 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002666 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002667 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002668 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002669 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002671 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002672 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2673 OnuId: int32(onuID), // OnuId not required
2674 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002675 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002676 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002677 AllocId: int32(allocID), // AllocId not used
2678 NetworkIntfId: int32(networkInterfaceID),
2679 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002680 Classifier: classifierProto,
2681 Action: actionProto,
2682 Priority: int32(logicalFlow.Priority),
2683 Cookie: logicalFlow.Cookie,
2684 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002685 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002686 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002687 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002688 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002689 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002690}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002691
Esin Karamanae41e2b2019-12-17 18:13:13 +00002692//getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
2693func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2694 var packetType string
2695 ovid, ivid := false, false
2696 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2697 vid := vlanID & VlanvIDMask
2698 if vid != ReservedVlan {
2699 ovid = true
2700 }
2701 }
2702 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2703 vid := uint32(metadata)
2704 if vid != ReservedVlan {
2705 ivid = true
2706 }
2707 }
2708 if ovid && ivid {
2709 packetType = DoubleTag
2710 } else if !ovid && !ivid {
2711 packetType = Untagged
2712 } else {
2713 packetType = SingleTag
2714 }
2715 return packetType
2716}
2717
2718//addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002719func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002720 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002721 action := make(map[string]interface{})
2722 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2723 action[TrapToHost] = true
2724 /* We manage flowId resource pool on per PON port basis.
2725 Since this situation is tricky, as a hack, we pass the NNI port
2726 index (network_intf_id) as PON port Index for the flowId resource
2727 pool. Also, there is no ONU Id available for trapping packets
2728 on NNI port, use onu_id as -1 (invalid)
2729 ****************** CAVEAT *******************
2730 This logic works if the NNI Port Id falls within the same valid
2731 range of PON Port Ids. If this doesn't work for some OLT Vendor
2732 we need to have a re-look at this.
2733 *********************************************
2734 */
2735 onuID := -1
2736 uniID := -1
2737 gemPortID := -1
2738 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002739 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002740 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302741 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002742 "classifier": classifier,
2743 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002744 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002745 }
yasin saplibddc2d72022-02-08 13:10:17 +00002746 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002747 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002748 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002749 return nil
yasin saplid0566272021-12-21 09:10:30 +00002750 } else if err != nil {
2751 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2752 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2753 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002754 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002755
David K. Bainbridge794735f2020-02-11 21:01:37 -08002756 classifierProto, err := makeOpenOltClassifierField(classifier)
2757 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002758 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002759 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002760 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002761 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002762 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002763 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002764 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002765 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002766 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2767 OnuId: int32(onuID), // OnuId not required
2768 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002769 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002770 FlowType: Downstream,
2771 AllocId: int32(allocID), // AllocId not used
2772 NetworkIntfId: int32(networkInterfaceID),
2773 GemportId: int32(gemPortID), // GemportId not used
2774 Classifier: classifierProto,
2775 Action: actionProto,
2776 Priority: int32(logicalFlow.Priority),
2777 Cookie: logicalFlow.Cookie,
2778 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002779 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002780 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002781 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002782 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002783
David K. Bainbridge794735f2020-02-11 21:01:37 -08002784 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002785}
2786
salmansiddiqui7ac62132019-08-22 03:58:50 +00002787func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2788 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302789 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002790 }
2791 if Dir == tp_pb.Direction_UPSTREAM {
2792 return "upstream", nil
2793 } else if Dir == tp_pb.Direction_DOWNSTREAM {
2794 return "downstream", nil
2795 }
2796 return "", nil
2797}
2798
Kent Hagermane6ff1012020-07-14 15:07:53 -04002799// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302800func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002801 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002802 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002803 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002804 intfID := args[IntfID]
2805 onuID := args[OnuID]
2806 uniID := args[UniID]
2807 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002808 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002809 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002810 gemToAes := make(map[uint32]bool)
2811
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002812 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002813 var direction = tp_pb.Direction_UPSTREAM
2814 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002815 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002816 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002817 attributes = TpInst.UpstreamGemPortAttributeList
2818 } else {
2819 attributes = TpInst.DownstreamGemPortAttributeList
2820 direction = tp_pb.Direction_DOWNSTREAM
2821 }
2822 default:
2823 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002824 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002825 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002826
2827 if len(gemPorts) == 1 {
2828 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002829 gemPortID = gemPorts[0]
2830 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002831 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2832 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002833 pBitMap := attributes[idx].PbitMap
2834 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2835 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2836 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002837 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002838 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2839 if pbitSet == pbit1 {
2840 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2841 pbitToGem[pcp] = gemID
2842 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002843 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002844 }
2845 }
2846 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002847 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2848 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2849 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002850 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002851 }
2852
Gamze Abaka7650be62021-02-26 10:50:36 +00002853 flowContext := &flowContext{intfID, onuID, uniID, portNo, classifierInfo, actionInfo,
2854 flow, allocID, gemPortID, tpID, pbitToGem, gemToAes}
2855
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 if ipProto, ok := classifierInfo[IPProto]; ok {
2857 if ipProto.(uint32) == IPProtoDhcp {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002858 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002859 "tp-id": tpID,
2860 "alloc-id": allocID,
2861 "intf-id": intfID,
2862 "onu-id": onuID,
2863 "uni-id": uniID,
2864 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002865 //Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002866 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002867 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002868 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})
2869 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002870 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 }
2872
Girish Gowdra32625212020-04-29 11:26:35 -07002873 } else if ipProto.(uint32) == IgmpProto {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002874 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302875 log.Fields{
2876 "intf-id": intfID,
2877 "onu-id": onuID,
2878 "uni-id": uniID,
2879 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002880 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002881 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002882 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})
2883 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002884 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002885 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002886 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002887 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002888 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002889 }
2890 } else if ethType, ok := classifierInfo[EthType]; ok {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002891 if ethType.(uint32) == EapEthType {
2892 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002893 "intf-id": intfID,
2894 "onu-id": onuID,
2895 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002896 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002897 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002898 var vlanID uint32
2899 if val, ok := classifierInfo[VlanVid]; ok {
2900 vlanID = (val.(uint32)) & VlanvIDMask
2901 } else {
2902 vlanID = DefaultMgmtVlan
2903 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002904 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002905 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002906 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})
2907 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002908 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002909 }
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002910 } else if ethType.(uint32) == PPPoEDEthType {
2911 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2912 "tp-id": tpID,
2913 "alloc-id": allocID,
2914 "intf-id": intfID,
2915 "onu-id": onuID,
2916 "uni-id": uniID,
2917 })
2918 //Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002919 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002920 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002921 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})
2922 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002923 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002924 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002925 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002926 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002927 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002928 "intf-id": intfID,
2929 "onu-id": onuID,
2930 "uni-id": uniID,
2931 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002932 //Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002933 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002934 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002935 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})
2936 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002937 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002938 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002939 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002940 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002941 "intf-id": intfID,
2942 "onu-id": onuID,
2943 "uni-id": uniID,
2944 })
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002945 //Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002946 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002947 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002948 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})
2949 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002950 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002951 }
2952 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002953 return olterrors.NewErrInvalidValue(log.Fields{
2954 "intf-id": intfID,
2955 "onu-id": onuID,
2956 "uni-id": uniID,
2957 "classifier": classifierInfo,
2958 "action": actionInfo,
2959 "flow": flow},
2960 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 }
2962 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04002963 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002964 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04002965 logger.Warn(ctx, err)
2966 }
2967 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002968 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969}
2970
Gamze Abakacb0e6772021-06-10 08:32:12 +00002971func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002972 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
2973 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
2974 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 +05302975 for i := 0; i < len(tpInstances); i++ {
2976 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00002977 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002978 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002979 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00002980 log.Fields{
2981 "device-id": f.deviceHandler.device.Id,
2982 "intfID": sq.intfID,
2983 "onuID": sq.onuID,
2984 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002985 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00002986 })
2987 return true
Girish Gowdra54934262019-11-13 14:19:55 +05302988 }
2989 }
2990 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00002991 return false
Gamze Abakafee36392019-10-03 11:17:24 +00002992}
2993
Neha Sharma96b7bf22020-06-15 10:37:32 +00002994func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07002995 for _, field := range flows.GetOfbFields(flow) {
2996 if field.Type == flows.ETH_TYPE {
salmansiddiqui7ac62132019-08-22 03:58:50 +00002997 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00002999 } else if field.Type == flows.ETH_DST {
3000 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003001 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
3002 } else if field.Type == flows.ETH_SRC {
3003 classifierInfo[EthSrc] = field.GetEthSrc()
3004 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
Scott Baker355d1742019-10-24 10:57:52 -07003005 } else if field.Type == flows.IP_PROTO {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003006 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003007 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003008 } else if field.Type == flows.IN_PORT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003010 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003011 } else if field.Type == flows.VLAN_VID {
Andrea Campanellafaa42152021-10-28 11:50:56 +05303012 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3013 if field.GetVlanVid() != ReservedVlan {
3014 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3015 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3016 }
Scott Baker355d1742019-10-24 10:57:52 -07003017 } else if field.Type == flows.VLAN_PCP {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003018 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003019 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003020 } else if field.Type == flows.UDP_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003021 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003022 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003023 } else if field.Type == flows.UDP_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003025 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003026 } else if field.Type == flows.IPV4_DST {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003027 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003028 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003029 } else if field.Type == flows.IPV4_SRC {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003030 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003031 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003032 } else if field.Type == flows.METADATA {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003033 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003034 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
Scott Baker355d1742019-10-24 10:57:52 -07003035 } else if field.Type == flows.TUNNEL_ID {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003036 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003037 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003038 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003039 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003040 return
3041 }
3042 }
3043}
3044
Neha Sharma96b7bf22020-06-15 10:37:32 +00003045func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003046 for _, action := range flows.GetActions(flow) {
3047 if action.Type == flows.OUTPUT {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003048 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003049 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003050 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003051 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003052 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003053 }
Scott Baker355d1742019-10-24 10:57:52 -07003054 } else if action.Type == flows.POP_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003056 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
Scott Baker355d1742019-10-24 10:57:52 -07003057 } else if action.Type == flows.PUSH_VLAN {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003058 if out := action.GetPush(); out != nil {
3059 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003060 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003061 } else {
3062 actionInfo[PushVlan] = true
3063 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003064 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303065 log.Fields{
3066 "push-tpid": actionInfo[TPID].(uint32),
3067 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003068 }
3069 }
Scott Baker355d1742019-10-24 10:57:52 -07003070 } else if action.Type == flows.SET_FIELD {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 if out := action.GetSetField(); out != nil {
3072 if field := out.GetField(); field != nil {
3073 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003074 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003075 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003076 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3077 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 }
3079 }
Esin Karamanccb714b2019-11-29 15:02:06 +00003080 } else if action.Type == flows.GROUP {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003082 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003083 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 }
3085 }
3086 return nil
3087}
3088
Neha Sharma96b7bf22020-06-15 10:37:32 +00003089func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003090 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003091 fieldtype := ofbField.GetType()
3092 if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID {
Esin Karamanccb714b2019-11-29 15:02:06 +00003093 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3094 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003095 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003096 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003098 }
Gamze Abakac43a66e2020-05-11 11:00:42 +00003099 } else if fieldtype == ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP {
3100 pcp := ofbField.GetVlanPcp()
3101 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003102 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003103 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003104 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003105 }
3106 }
3107}
3108
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003110 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003112 } else {
3113 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003114 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003115 }
3116}
3117
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003119 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003120 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003122 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003123 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303126 log.Fields{
3127 "newinport": classifierInfo[InPort].(uint32),
3128 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003129 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303130 return olterrors.NewErrNotFound("child-in-port",
3131 log.Fields{
3132 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3133 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 }
3135 }
3136 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003138 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003139 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003140 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003141 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003142 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303143 log.Fields{
3144 "newoutport": actionInfo[Output].(uint32),
3145 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303147 return olterrors.NewErrNotFound("out-port",
3148 log.Fields{
3149 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3150 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 }
3152 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003153 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003154 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003155 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003156 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303157 log.Fields{
3158 "newinport": actionInfo[Output].(uint32),
3159 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003160 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303161 return olterrors.NewErrNotFound("nni-port",
3162 log.Fields{
3163 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3164 "in-port": classifierInfo[InPort].(uint32),
3165 "out-port": actionInfo[Output].(uint32),
3166 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003167 }
3168 }
3169 }
3170 return nil
3171}
Gamze Abakafee36392019-10-03 11:17:24 +00003172
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003174 /* Metadata 8 bytes:
3175 Most Significant 2 Bytes = Inner VLAN
3176 Next 2 Bytes = Tech Profile ID(TPID)
3177 Least Significant 4 Bytes = Port ID
3178 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3179 subscriber related flows.
3180 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003181 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003182 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003183 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003184 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003186 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003187}
3188
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003189func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003190 for _, sliceElement := range slice {
3191 if sliceElement == item {
3192 return slice
3193 }
3194 }
3195 return append(slice, item)
3196}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303197
3198// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303200
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003201 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303202 if portType == voltha.Port_PON_OLT {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003203 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003204 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003205 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003206 log.Fields{
3207 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003208 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003209 return uint32(0), err
3210 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303212 return intfID, nil
3213 } else if portType == voltha.Port_ETHERNET_NNI {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003214 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003215 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003217 log.Fields{
3218 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003219 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003220 return uint32(0), err
3221 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003222 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303223 return intfID, nil
3224 }
3225 return uint32(0), nil
3226}
3227
3228// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003229func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3230 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3231 if err != nil {
3232 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3233 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3234 return
3235 }
3236 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003237
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003238 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003239 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003240 f.packetInGemPortLock.RUnlock()
3241
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303242 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003243 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003244 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 +05303245 log.Fields{
3246 "pktinkey": pktInkey,
3247 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003248 return
3249 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303250 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003251 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003252 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003253 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003254
npujarec5762e2020-01-01 14:08:48 +05303255 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003256 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 +05303257 log.Fields{
3258 "pktinkey": pktInkey,
3259 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303260}
3261
Esin Karaman7fb80c22020-07-16 14:23:33 +00003262//getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
3263func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
3264 if packet == nil || len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003265 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003266 return 0, 0, errors.New("invalid packet length")
3267 }
3268 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3269 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3270
3271 var index int8
3272 if outerEthType == 0x8100 {
3273 if innerEthType == 0x8100 {
3274 // q-in-q 802.1ad or 802.1q double tagged packet.
3275 // get the inner vlanId
3276 index = 18
3277 } else {
3278 index = 14
3279 }
3280 priority := (packet[index] >> 5) & 0x7
3281 //13 bits composes vlanId value
3282 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3283 return vlan, priority, nil
3284 }
3285 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3286 return 0, 0, nil
3287}
3288
Girish Gowdra9602eb42020-09-09 15:50:39 -07003289//clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
3290// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003291func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003292 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003293 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3294 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003295 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003296 "flow-id": flow.Id,
3297 "device-id": f.deviceHandler.device.Id})
3298 // Remove from device
3299 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3300 // DKB
3301 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3302 log.Fields{
3303 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003304 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003305 return err
3306 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003307
3308 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003309}
3310
khenaidoodc2116e2021-10-19 17:33:19 -04003311func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003312 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003313 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003314 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003315 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003316 }
3317
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003318 switch tpInst := tpInst.(type) {
3319 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003320 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003321 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003322 DeviceId: onuDeviceID,
3323 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003324 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003325 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003326 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003327 case *tp_pb.EponTechProfileInstance:
3328 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003329 DeviceId: onuDeviceID,
3330 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003331 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003332 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003333 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003334 default:
3335 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003336 }
khenaidoodc2116e2021-10-19 17:33:19 -04003337 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003338 DeviceId: onuDeviceID,
3339 UniId: uniID,
3340 TpInstancePath: tpPath,
3341 TechTpInstance: nil,
3342 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003343}
3344
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003345// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3346func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
3347
3348 intfID := sq.intfID
3349 onuID := sq.onuID
3350 uniID := sq.uniID
3351 tpID := sq.tpID
3352
3353 var reverseDirection string
3354 if sq.direction == tp_pb.Direction_UPSTREAM {
3355 reverseDirection = "downstream"
3356 } else {
3357 reverseDirection = "upstream"
3358 }
3359
3360 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003361 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003362 return
3363 }
3364
3365 // revert-delete tech-profile instance and delete tech profile id for onu
3366 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})
3367 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3368 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003369 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003370
3371 // free gem/alloc
3372 switch techprofileInst := sq.tpInst.(type) {
3373 case *tp_pb.TechProfileInstance:
3374 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003375 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003376 }
yasin saplibddc2d72022-02-08 13:10:17 +00003377 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003378 }
3379}
3380
3381// revertSchduler is called when CreateQueues request fails
3382func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3383 // revert scheduler
3384 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})
3385 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(ctx, &tp_pb.TrafficSchedulers{
3386 IntfId: sq.intfID, OnuId: sq.onuID,
3387 UniId: sq.uniID, PortNo: sq.uniPort,
3388 TrafficScheds: TrafficSched})
3389}
Girish Gowdra6071f382021-12-14 12:52:04 +05303390
3391// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3392func (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 +00003393 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303394 if err != nil {
3395 return olterrors.NewErrNotFound("meter",
3396 log.Fields{"intf-id": intfID,
3397 "onu-id": onuID,
3398 "uni-id": uniID,
3399 "device-id": f.deviceHandler.device.Id}, err)
3400 }
3401
3402 if meterInfo != nil {
3403 // If RefCnt become 0 clear the meter information from the DB.
3404 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003405 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303406 return err
3407 }
3408 } else if meterInfo.MeterID != meterID {
3409 logger.Errorw(ctx, "meter-mismatch-for-direction",
3410 log.Fields{"direction": direction,
3411 "kv-store-meter-id": meterInfo.MeterID,
3412 "meter-id-in-flow": meterID,
3413 "device-id": f.deviceHandler.device.Id})
3414 return olterrors.NewErrInvalidValue(log.Fields{
3415 "unsupported": "meter-id",
3416 "kv-store-meter-id": meterInfo.MeterID,
3417 "meter-id-in-flow": meterID,
3418 "device-id": f.deviceHandler.device.Id}, nil)
3419 }
3420 }
3421 return nil
3422}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003423
3424func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3425 /* After we successfully remove the scheduler configuration on the OLT device,
3426 * delete the meter id on the KV store.
3427 */
yasin saplibddc2d72022-02-08 13:10:17 +00003428 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003429 if err != nil {
3430 return olterrors.NewErrAdapter("unable-to-remove-meter",
3431 log.Fields{
3432 "onu": sq.onuID,
3433 "device-id": f.deviceHandler.device.Id,
3434 "intf-id": sq.intfID,
3435 "onu-id": sq.onuID,
3436 "uni-id": sq.uniID,
3437 "uni-port": sq.uniPort}, err)
3438 }
3439 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3440 log.Fields{
3441 "dir": direction,
3442 "device-id": f.deviceHandler.device.Id,
3443 "intf-id": sq.intfID,
3444 "onu-id": sq.onuID,
3445 "uni-id": sq.uniID,
3446 "uni-port": sq.uniPort})
3447 return err
3448}