blob: ca1b904a0cc481f498a34d26ffb1936c9f2a2fc4 [file] [log] [blame]
manikkaraj kbf256be2019-03-25 00:13:48 +05301/*
Joey Armstrong11f5a572024-01-12 19:11:32 -05002 * Copyright 2018-2024 Open Networking Foundation (ONF) and the ONF Contributors
manikkaraj kbf256be2019-03-25 00:13:48 +05303
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
Joey Armstrong3f0e2422023-07-05 18:25:41 -040017// Package core provides the utility for olt devices, flows and statistics
Scott Bakerdbd960e2020-02-28 08:57:51 -080018package 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 (
Akash Kankanala041a2122024-10-16 15:49:22 +053050 // IPProtoDhcp flow category
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070051 IPProtoDhcp = 17
manikkaraj kbf256be2019-03-25 00:13:48 +053052
Akash Kankanala041a2122024-10-16 15:49:22 +053053 // IgmpProto proto value
Girish Gowdraa09aeab2020-09-14 16:30:52 -070054 IgmpProto = 2
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070055
Akash Kankanala041a2122024-10-16 15:49:22 +053056 // EapEthType eapethtype value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070057 EapEthType = 0x888e
Akash Kankanala041a2122024-10-16 15:49:22 +053058 // LldpEthType lldp ethtype value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070059 LldpEthType = 0x88cc
Akash Kankanala041a2122024-10-16 15:49:22 +053060 // IPv4EthType IPv4 ethernet type value
Esin Karamanae41e2b2019-12-17 18:13:13 +000061 IPv4EthType = 0x800
Akash Kankanala041a2122024-10-16 15:49:22 +053062 // PPPoEDEthType PPPoE discovery ethernet type value
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -030063 PPPoEDEthType = 0x8863
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070064
Akash Kankanala041a2122024-10-16 15:49:22 +053065 // ReservedVlan Transparent Vlan (Masked Vlan, VLAN_ANY in ONOS Flows)
Andrea Campanella7acc0b92020-02-14 09:20:49 +010066 ReservedVlan = 4096
Harsh Awasthiea45af72019-08-26 02:39:00 -040067
Akash Kankanala041a2122024-10-16 15:49:22 +053068 // DefaultMgmtVlan default vlan value
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070069 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
Akash Kankanala041a2122024-10-16 15:49:22 +053073 // Upstream constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070074 Upstream = "upstream"
Akash Kankanala041a2122024-10-16 15:49:22 +053075 // Downstream constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070076 Downstream = "downstream"
Akash Kankanala041a2122024-10-16 15:49:22 +053077 // Multicast constant
Esin Karamanccb714b2019-11-29 15:02:06 +000078 Multicast = "multicast"
Akash Kankanala041a2122024-10-16 15:49:22 +053079 // PacketTagType constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070080 PacketTagType = "pkt_tag_type"
Akash Kankanala041a2122024-10-16 15:49:22 +053081 // Untagged constant
David K. Bainbridge82efc492019-09-04 09:57:11 -070082 Untagged = "untagged"
Akash Kankanala041a2122024-10-16 15:49:22 +053083 // SingleTag constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070084 SingleTag = "single_tag"
Akash Kankanala041a2122024-10-16 15:49:22 +053085 // DoubleTag constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070086 DoubleTag = "double_tag"
manikkaraj kbf256be2019-03-25 00:13:48 +053087
88 // classifierInfo
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070089
Akash Kankanala041a2122024-10-16 15:49:22 +053090 // EthType constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070091 EthType = "eth_type"
Akash Kankanala041a2122024-10-16 15:49:22 +053092 // EthDst constant
Esin Karamanccb714b2019-11-29 15:02:06 +000093 EthDst = "eth_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +053094 // EthSrc constant
Girish Gowdraffa52e52022-02-16 15:48:10 -080095 EthSrc = "eth_src"
Akash Kankanala041a2122024-10-16 15:49:22 +053096 // TPID constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070097 TPID = "tpid"
Akash Kankanala041a2122024-10-16 15:49:22 +053098 // IPProto constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -070099 IPProto = "ip_proto"
Akash Kankanala041a2122024-10-16 15:49:22 +0530100 // InPort constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700101 InPort = "in_port"
Akash Kankanala041a2122024-10-16 15:49:22 +0530102 // VlanVid constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700103 VlanVid = "vlan_vid"
Akash Kankanala041a2122024-10-16 15:49:22 +0530104 // VlanPcp constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700105 VlanPcp = "vlan_pcp"
106
Akash Kankanala041a2122024-10-16 15:49:22 +0530107 // UDPDst constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700108 UDPDst = "udp_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +0530109 // UDPSrc constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700110 UDPSrc = "udp_src"
Akash Kankanala041a2122024-10-16 15:49:22 +0530111 // Ipv4Dst constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700112 Ipv4Dst = "ipv4_dst"
Akash Kankanala041a2122024-10-16 15:49:22 +0530113 // Ipv4Src constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700114 Ipv4Src = "ipv4_src"
Akash Kankanala041a2122024-10-16 15:49:22 +0530115 // Metadata constant
David K. Bainbridge82efc492019-09-04 09:57:11 -0700116 Metadata = "metadata"
Akash Kankanala041a2122024-10-16 15:49:22 +0530117 // TunnelID constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700118 TunnelID = "tunnel_id"
Akash Kankanala041a2122024-10-16 15:49:22 +0530119 // Output constant
David K. Bainbridge82efc492019-09-04 09:57:11 -0700120 Output = "output"
Akash Kankanala041a2122024-10-16 15:49:22 +0530121 // GroupID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000122 GroupID = "group_id"
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700123 // Actions
124
Akash Kankanala041a2122024-10-16 15:49:22 +0530125 // PopVlan constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700126 PopVlan = "pop_vlan"
Akash Kankanala041a2122024-10-16 15:49:22 +0530127 // PushVlan constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700128 PushVlan = "push_vlan"
Akash Kankanala041a2122024-10-16 15:49:22 +0530129 // TrapToHost constant
Girish Gowdru6a80bbd2019-07-02 07:36:09 -0700130 TrapToHost = "trap_to_host"
Akash Kankanala041a2122024-10-16 15:49:22 +0530131 // MaxMeterBand constant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400132 MaxMeterBand = 2
Akash Kankanala041a2122024-10-16 15:49:22 +0530133 // VlanPCPMask contant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400134 VlanPCPMask = 0xFF
Akash Kankanala041a2122024-10-16 15:49:22 +0530135 // VlanvIDMask constant
Manikkaraj kb1d51442019-07-23 10:41:02 -0400136 VlanvIDMask = 0xFFF
Akash Kankanala041a2122024-10-16 15:49:22 +0530137 // IntfID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000138 IntfID = "intfId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530139 // OnuID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000140 OnuID = "onuId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530141 // UniID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000142 UniID = "uniId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530143 // PortNo constant
Gamze Abakafee36392019-10-03 11:17:24 +0000144 PortNo = "portNo"
Akash Kankanala041a2122024-10-16 15:49:22 +0530145 // AllocID constant
Gamze Abakafee36392019-10-03 11:17:24 +0000146 AllocID = "allocId"
Akash Kankanala041a2122024-10-16 15:49:22 +0530147 // GemID constant
Gamze Abakafcbd6e72020-12-17 13:25:16 +0000148 GemID = "gemId"
Esin Karamanccb714b2019-11-29 15:02:06 +0000149
Akash Kankanala041a2122024-10-16 15:49:22 +0530150 // NoneOnuID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000151 NoneOnuID = -1
Akash Kankanala041a2122024-10-16 15:49:22 +0530152 // NoneUniID constant
Esin Karamanccb714b2019-11-29 15:02:06 +0000153 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 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530163 tpInst interface{}
164 flowMetadata *ofp.FlowMetadata
Gamze Abakafee36392019-10-03 11:17:24 +0000165 direction tp_pb.Direction
166 intfID uint32
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530167 nniIntfID uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000168 onuID uint32
169 uniID uint32
170 tpID uint32
171 uniPort uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000172 meterID uint32
Gamze Abakafee36392019-10-03 11:17:24 +0000173}
174
Gamze Abaka7650be62021-02-26 10:50:36 +0000175type flowContext struct {
Akash Kankanala041a2122024-10-16 15:49:22 +0530176 classifier map[string]interface{}
177 action map[string]interface{}
178 logicalFlow *ofp.OfpFlowStats
179 pbitToGem map[uint32]uint32
180 gemToAes map[uint32]bool
Gamze Abaka7650be62021-02-26 10:50:36 +0000181 intfID uint32
182 onuID uint32
183 uniID uint32
184 portNo uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000185 allocID uint32
186 gemPortID uint32
187 tpID uint32
Gamze Abaka7650be62021-02-26 10:50:36 +0000188}
189
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700190// This control block is created per flow add/remove and pushed on the incomingFlows channel slice
191// The flowControlBlock is then picked by the perOnuFlowHandlerRoutine for further processing.
192// There is on perOnuFlowHandlerRoutine routine per ONU that constantly monitors for any incoming
193// flow and processes it serially
194type flowControlBlock struct {
khenaidoodc2116e2021-10-19 17:33:19 -0400195 ctx context.Context // Flow handler context
khenaidoodc2116e2021-10-19 17:33:19 -0400196 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
Akash Kankanala041a2122024-10-16 15:49:22 +0530199 addFlow bool // if true flow to be added, else removed
Esin Karamanccb714b2019-11-29 15:02:06 +0000200}
201
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400202// OpenOltFlowMgr creates the Structure of OpenOltFlowMgr obj
manikkaraj kbf256be2019-03-25 00:13:48 +0530203type OpenOltFlowMgr struct {
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
Akash Kankanala041a2122024-10-16 15:49:22 +0530209 packetInGemPort map[rsrcMgr.PacketInInfoKey]uint32 // packet in gem port local cache
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700210
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700211 // Slice of channels. Each channel in slice, index by ONU ID, queues flows per ONU.
212 // 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 -0700213 incomingFlows []chan flowControlBlock
214 stopFlowHandlerRoutine []chan bool
215 flowHandlerRoutineActive []bool
Akash Kankanala041a2122024-10-16 15:49:22 +0530216 packetInGemPortLock sync.RWMutex
217
218 ponPortIdx uint32 // Pon Port this FlowManager is responsible for
manikkaraj kbf256be2019-03-25 00:13:48 +0530219}
220
Holger Hildebrandt143b5be2023-02-10 08:28:15 +0000221// CloseKVClient closes open KV clients
222func (f *OpenOltFlowMgr) CloseKVClient(ctx context.Context) {
223 if f.techprofile != nil {
224 f.techprofile.CloseKVClient(ctx)
225 }
226}
227
Joey Armstrong3f0e2422023-07-05 18:25:41 -0400228// NewFlowManager creates OpenOltFlowMgr object and initializes the parameters
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700229func NewFlowManager(ctx context.Context, dh *DeviceHandler, rMgr *rsrcMgr.OpenOltResourceMgr, grpMgr *OpenOltGroupMgr, ponPortIdx uint32) *OpenOltFlowMgr {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000230 logger.Infow(ctx, "initializing-flow-manager", log.Fields{"device-id": dh.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530231 var flowMgr OpenOltFlowMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530232 var err error
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530233
manikkaraj kbf256be2019-03-25 00:13:48 +0530234 flowMgr.deviceHandler = dh
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700235 flowMgr.ponPortIdx = ponPortIdx
Girish Gowdra9602eb42020-09-09 15:50:39 -0700236 flowMgr.grpMgr = grpMgr
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530237 flowMgr.resourceMgr = rMgr
yasin saplid0566272021-12-21 09:10:30 +0000238 // dh.totalPonPorts is reserved for NNI trap flows. It doesn't need a tech profile
239 if ponPortIdx != dh.totalPonPorts {
240 if err = flowMgr.populateTechProfileForCurrentPonPort(ctx); err != nil {
241 logger.Errorw(ctx, "error-while-populating-tech-profile-mgr", log.Fields{"err": err})
242 return nil
243 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530244 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +0530245 flowMgr.packetInGemPort = make(map[rsrcMgr.PacketInInfoKey]uint32)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700246
247 // Create a slice of buffered channels for handling concurrent flows per ONU.
248 // 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 -0700249 flowMgr.incomingFlows = make([]chan flowControlBlock, plt.MaxOnusPerPon+1)
250 flowMgr.stopFlowHandlerRoutine = make([]chan bool, plt.MaxOnusPerPon+1)
251 flowMgr.flowHandlerRoutineActive = make([]bool, plt.MaxOnusPerPon+1)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700252 for i := range flowMgr.incomingFlows {
253 flowMgr.incomingFlows[i] = make(chan flowControlBlock, maxConcurrentFlowsPerOnu)
Girish Gowdraae56c722021-11-22 14:31:11 -0800254 flowMgr.stopFlowHandlerRoutine[i] = make(chan bool)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700255 // Spin up a go routine to handling incoming flows (add/remove).
256 // There will be on go routine per ONU.
257 // This routine will be blocked on the flowMgr.incomingFlows[onu-id] channel for incoming flows.
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700258 flowMgr.flowHandlerRoutineActive[i] = true
259 go flowMgr.perOnuFlowHandlerRoutine(i, flowMgr.incomingFlows[i], flowMgr.stopFlowHandlerRoutine[i])
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700260 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700261
Akash Kankanala041a2122024-10-16 15:49:22 +0530262 // load interface to multicast queue map from kv store
Girish Gowdra9602eb42020-09-09 15:50:39 -0700263 flowMgr.grpMgr.LoadInterfaceToMulticastQueueMap(ctx)
Neha Sharma96b7bf22020-06-15 10:37:32 +0000264 logger.Info(ctx, "initialization-of-flow-manager-success")
manikkaraj kbf256be2019-03-25 00:13:48 +0530265 return &flowMgr
266}
267
Kent Hagermane6ff1012020-07-14 15:07:53 -0400268func (f *OpenOltFlowMgr) registerFlow(ctx context.Context, flowFromCore *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
yasin saplid0566272021-12-21 09:10:30 +0000269 // In case of nni trap flow
270 if deviceFlow.AccessIntfId == -1 {
yasin saplibddc2d72022-02-08 13:10:17 +0000271 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.AccessIntfId), flowFromCore)
yasin saplid0566272021-12-21 09:10:30 +0000272 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700273 if !deviceFlow.ReplicateFlow && deviceFlow.GemportId > 0 {
274 // 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 +0000275 return f.resourceMgr.RegisterFlowIDForGem(ctx, uint32(deviceFlow.GemportId), flowFromCore)
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700276 } else if deviceFlow.ReplicateFlow && len(deviceFlow.PbitToGemport) > 0 {
277 // Flow is replicated in this case. We need to register the flow for all the gem-ports it is replicated to.
278 for _, gemPort := range deviceFlow.PbitToGemport {
yasin saplibddc2d72022-02-08 13:10:17 +0000279 if err := f.resourceMgr.RegisterFlowIDForGem(ctx, gemPort, flowFromCore); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700280 return err
281 }
Matteo Scandolo738c52a2020-08-03 11:14:22 -0700282 }
Gamze Abakafee36392019-10-03 11:17:24 +0000283 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700284 return nil
285}
286
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530287func (f *OpenOltFlowMgr) processAddFlow(ctx context.Context, intfID uint32, nni_port uint32, onuID uint32, uniID uint32, portNo uint32,
salmansiddiqui7ac62132019-08-22 03:58:50 +0000288 classifierInfo map[string]interface{}, actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpID uint32,
khenaidoodc2116e2021-10-19 17:33:19 -0400289 UsMeterID uint32, DsMeterID uint32, flowMetadata *ofp.FlowMetadata) error {
Gamze Abakafee36392019-10-03 11:17:24 +0000290 var allocID uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530291 var gemPorts []uint32
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700292 var TpInst interface{}
manikkaraj kbf256be2019-03-25 00:13:48 +0530293
Neha Sharma96b7bf22020-06-15 10:37:32 +0000294 logger.Infow(ctx, "dividing-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530295 "device-id": f.deviceHandler.device.Id,
296 "intf-id": intfID,
297 "onu-id": onuID,
298 "uni-id": uniID,
299 "port-no": portNo,
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700300 "classifier": classifierInfo,
Shrey Baid26912972020-04-16 21:02:31 +0530301 "action": actionInfo,
302 "usmeter-iD": UsMeterID,
303 "dsmeter-iD": DsMeterID,
304 "tp-id": TpID})
Matt Jeanneret77199612019-07-26 18:08:35 -0400305 // only create tcont/gemports if there is actually an onu id. otherwise BAL throws an error. Usually this
306 // is because the flow is an NNI flow and there would be no onu resources associated with it
307 // TODO: properly deal with NNI flows
Kent Hagermane6ff1012020-07-14 15:07:53 -0400308 if onuID == 0 {
Andrea Campanellabfe08432020-09-11 17:07:03 +0200309 cause := "no-onu-id-for-flow"
310 fields := log.Fields{
311 "onu": onuID,
312 "port-no": portNo,
313 "classifer": classifierInfo,
314 "action": actionInfo,
315 "device-id": f.deviceHandler.device.Id}
316 logger.Errorw(ctx, cause, fields)
317 return olterrors.NewErrNotFound(cause, fields, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +0530318 }
319
Matteo Scandolod625b4c2020-04-02 16:16:01 -0700320 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Neha Sharma96b7bf22020-06-15 10:37:32 +0000321 logger.Debugw(ctx, "uni-port-path", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530322 "uni": uni,
323 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530324
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700325 logger.Debugw(ctx, "dividing-flow-create-tcont-gem-ports", log.Fields{
326 "device-id": f.deviceHandler.device.Id,
327 "intf-id": intfID,
328 "onu-id": onuID,
329 "uni-id": uniID,
330 "port-no": portNo,
331 "classifier": classifierInfo,
332 "action": actionInfo,
333 "usmeter-id": UsMeterID,
334 "dsmeter-id": DsMeterID,
335 "tp-id": TpID})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530336 allocID, gemPorts, TpInst = f.createTcontGemports(ctx, intfID, nni_port, onuID, uniID, uni, portNo, TpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700337 if allocID == 0 || gemPorts == nil || TpInst == nil {
338 logger.Error(ctx, "alloc-id-gem-ports-tp-unavailable")
339 return olterrors.NewErrNotFound(
340 "alloc-id-gem-ports-tp-unavailable",
341 nil, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400342 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -0700343 args := make(map[string]uint32)
344 args[IntfID] = intfID
345 args[OnuID] = onuID
346 args[UniID] = uniID
347 args[PortNo] = portNo
348 args[AllocID] = allocID
349
350 /* Flows can be added specific to gemport if p-bits are received.
351 * If no pbit mentioned then adding flows for all gemports
352 */
Gamze Abaka6d0a64f2021-11-18 08:08:33 +0000353 return f.checkAndAddFlow(ctx, args, classifierInfo, actionInfo, flow, TpInst, gemPorts, TpID, uni)
manikkaraj kbf256be2019-03-25 00:13:48 +0530354}
355
salmansiddiqui7ac62132019-08-22 03:58:50 +0000356// CreateSchedulerQueues creates traffic schedulers on the device with the given scheduler configuration and traffic shaping info
Girish Gowdraf3728b12022-02-02 21:46:51 -0800357// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +0530358func (f *OpenOltFlowMgr) CreateSchedulerQueues(ctx context.Context, sq schedQueue) error {
nikesh.krishnan81ec7442023-10-31 17:19:34 +0530359 logger.Debugw(ctx, "CreateSchedulerQueues",
Shrey Baid26912972020-04-16 21:02:31 +0530360 log.Fields{"dir": sq.direction,
361 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530362 "nniIntfID": sq.nniIntfID,
Shrey Baid26912972020-04-16 21:02:31 +0530363 "onu-id": sq.onuID,
364 "uni-id": sq.uniID,
365 "tp-id": sq.tpID,
366 "meter-id": sq.meterID,
367 "tp-inst": sq.tpInst,
368 "flowmetadata": sq.flowMetadata,
369 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400370
Girish Gowdra6071f382021-12-14 12:52:04 +0530371 direction, err := verifyMeterIDAndGetDirection(sq.meterID, sq.direction)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000372 if err != nil {
373 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400374 }
375
Girish Gowdraf3728b12022-02-02 21:46:51 -0800376 var TrafficShaping *tp_pb.TrafficShapingInfo
377 if sq.flowMetadata == nil || len(sq.flowMetadata.Meters) != 1 {
378 return olterrors.NewErrInvalidValue(log.Fields{
379 "reason": "invalid-meter-config",
380 "meter-id": sq.meterID,
381 "device-id": f.deviceHandler.device.Id}, nil)
382 }
383
384 if TrafficShaping, err = meters.GetTrafficShapingInfo(ctx, sq.flowMetadata.Meters[0]); err != nil {
385 return olterrors.NewErrInvalidValue(log.Fields{
386 "reason": "invalid-meter-config",
387 "meter-id": sq.meterID,
388 "device-id": f.deviceHandler.device.Id}, nil)
389 }
390
391 var SchedCfg *tp_pb.SchedulerConfig
mgouda86543582025-10-29 20:58:16 +0530392 switch sq.direction {
393 case tp_pb.Direction_UPSTREAM:
Girish Gowdraf3728b12022-02-02 21:46:51 -0800394 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
mgouda86543582025-10-29 20:58:16 +0530395 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdraf3728b12022-02-02 21:46:51 -0800396 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
397 }
398 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
399 TrafficSched[0].TechProfileId = sq.tpID
400
Manikkaraj kb1d51442019-07-23 10:41:02 -0400401 /* Lets make a simple assumption that if the meter-id is present on the KV store,
402 * then the scheduler and queues configuration is applied on the OLT device
403 * in the given direction.
404 */
yasin saplibddc2d72022-02-08 13:10:17 +0000405 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400406 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530407 return olterrors.NewErrNotFound("meter",
408 log.Fields{"intf-id": sq.intfID,
409 "onu-id": sq.onuID,
410 "uni-id": sq.uniID,
411 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400412 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000413
Girish Gowdraf3728b12022-02-02 21:46:51 -0800414 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530415 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800416 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530417 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
yasin saplibddc2d72022-02-08 13:10:17 +0000418 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800419 return err
420 }
421
422 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
423 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
424 // Just create gem ports and traffic queues on the current uni for the given service
425 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
426 log.Fields{"intf-id": sq.intfID,
427 "onu-id": sq.onuID,
428 "uni-id": sq.uniID,
429 "tp-id": sq.tpID,
430 "device-id": f.deviceHandler.device.Id})
431 // The upstream scheduler is already created. We only need to create the queues
432 // If there are multiple upstream flows on a given uni, then it is possible that
433 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
434 // TODO: Find better mechanism to not duplicate request.
435 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
436 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
437 log.Fields{"intf-id": sq.intfID,
438 "direction": sq.direction,
439 "device-id": f.deviceHandler.device.Id}, err)
440 }
441 } else {
442 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
443 log.Fields{"intf-id": sq.intfID,
444 "onu-id": sq.onuID,
445 "uni-id": sq.uniID,
446 "tp-id": sq.tpID,
447 "device-id": f.deviceHandler.device.Id})
448 }
449 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400450 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000451
Neha Sharma96b7bf22020-06-15 10:37:32 +0000452 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530453 log.Fields{
454 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530455 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530456 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000457
Girish Gowdraa482f272021-03-24 23:04:19 -0700458 found := false
459 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000460 if sq.flowMetadata != nil {
461 for _, meter := range sq.flowMetadata.Meters {
462 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700463 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700464 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 +0000465 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700466 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530467 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700468 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400469 break
470 }
471 }
472 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000473 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400474 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700475 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530476 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800477 "reason": "Could-not-get-meterbands-from-flowMetadata",
478 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530479 "meter-id": sq.meterID,
480 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400481 }
Gamze Abaka01174422021-03-10 06:55:27 +0000482
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700483 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530484 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
485 log.Fields{"intf-id": sq.intfID,
486 "direction": sq.direction,
487 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400488 }
489
salmansiddiqui7ac62132019-08-22 03:58:50 +0000490 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400491 * store the meter id on the KV store, for further reference.
492 */
yasin saplibddc2d72022-02-08 13:10:17 +0000493 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530494 return olterrors.NewErrAdapter("failed-updating-meter-id",
495 log.Fields{"onu-id": sq.onuID,
496 "meter-id": sq.meterID,
497 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400498 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000499 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530500 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700501 "meter-info": meterInfo,
502 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400503 return nil
504}
505
Girish Gowdraf3728b12022-02-02 21:46:51 -0800506func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
507 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
508 if err != nil {
509 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
510 log.Fields{"intf-id": sq.intfID,
511 "direction": sq.direction,
512 "device-id": f.deviceHandler.device.Id}, err)
513 }
514 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
515 log.Fields{"direction": sq.direction,
516 "traffic-queues": trafficQueues,
517 "device-id": f.deviceHandler.device.Id})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530518 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, NetworkIntfId: sq.nniIntfID, OnuId: sq.onuID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800519 UniId: sq.uniID, PortNo: sq.uniPort,
520 TrafficQueues: trafficQueues,
521 TechProfileId: TrafficSched[0].TechProfileId}
bseenivaa1622112025-12-11 18:24:02 +0530522 subCtx1, cancel1 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
523 if _, err = f.deviceHandler.Client.CreateTrafficQueues(subCtx1, queues); err != nil {
524 cancel1()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800525 if len(queues.TrafficQueues) > 1 {
526 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
bseenivaa1622112025-12-11 18:24:02 +0530527 subCtx2, cancel2 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
528 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(subCtx2, queues)
529 cancel2()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800530 }
531 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
532 }
bseenivaa1622112025-12-11 18:24:02 +0530533 cancel1()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800534 return err
535}
536
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700537func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700538 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000539
540 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530541 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
542 log.Fields{"intf-id": sq.intfID,
543 "direction": sq.direction,
544 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000545 }
546
Gamze Abakacb0e6772021-06-10 08:32:12 +0000547 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
548 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
549 log.Fields{
550 "direction": sq.direction,
551 "TrafficScheds": TrafficSched,
552 "device-id": f.deviceHandler.device.Id,
553 "intfID": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530554 "nniIntfID": sq.nniIntfID,
Gamze Abakacb0e6772021-06-10 08:32:12 +0000555 "onuID": sq.onuID,
556 "uniID": sq.uniID})
bseenivaa1622112025-12-11 18:24:02 +0530557 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
558 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Gamze Abakacb0e6772021-06-10 08:32:12 +0000559 IntfId: sq.intfID, OnuId: sq.onuID,
560 UniId: sq.uniID, PortNo: sq.uniPort,
561 TrafficScheds: TrafficSched}); err != nil {
bseenivaa1622112025-12-11 18:24:02 +0530562 cancel()
Gamze Abakacb0e6772021-06-10 08:32:12 +0000563 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
564 }
bseenivaa1622112025-12-11 18:24:02 +0530565 cancel()
Gamze Abakacb0e6772021-06-10 08:32:12 +0000566 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
567 "direction": sq.direction,
568 "traffic-queues": trafficQueues,
569 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000570 }
571
572 // On receiving the CreateTrafficQueues request, the driver should create corresponding
573 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000574 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530575 log.Fields{"direction": sq.direction,
576 "traffic-queues": trafficQueues,
577 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000578 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530579 NetworkIntfId: sq.nniIntfID,
580 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000581 TrafficQueues: trafficQueues,
582 TechProfileId: TrafficSched[0].TechProfileId}
bseenivaa1622112025-12-11 18:24:02 +0530583 subCtx1, cancel1 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
584 if _, err := f.deviceHandler.Client.CreateTrafficQueues(subCtx1, queues); err != nil {
585 cancel1()
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000586 if len(queues.TrafficQueues) > 1 {
587 logger.Debug(ctx, "removing-queues-for-1tcont-multi-gem", log.Fields{"intfID": sq.intfID, "onuID": sq.onuID, "dir": sq.direction})
bseenivaa1622112025-12-11 18:24:02 +0530588 subCtx2, cancel2 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
589 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(subCtx2, queues)
590 cancel2()
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000591 }
592 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530593 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000594 }
bseenivaa1622112025-12-11 18:24:02 +0530595 cancel1()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000596 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530597 "direction": sq.direction,
598 "traffic-queues": trafficQueues,
599 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000600
Esin Karamanccb714b2019-11-29 15:02:06 +0000601 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700602 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000603 if len(multicastTrafficQueues) > 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530604 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { // assumed that there is only one queue per PON for the multicast service
605 // the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
606 // just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000607 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000608 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700609 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000610 gemPortID: multicastQueuePerPonPort.GemportId,
611 servicePriority: multicastQueuePerPonPort.Priority,
612 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700613 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Akash Kankanala041a2122024-10-16 15:49:22 +0530614 // also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000615 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700616 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400617 return err
618 }
Shrey Baid26912972020-04-16 21:02:31 +0530619
Neha Sharma96b7bf22020-06-15 10:37:32 +0000620 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000621 }
622 }
623 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000624 return nil
625}
626
Girish Gowdraf3728b12022-02-02 21:46:51 -0800627// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
628func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
629 var err error
630 logger.Infow(ctx, "removing-queue-in-olt",
631 log.Fields{
632 "direction": sq.direction,
633 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530634 "nniIntfID": sq.nniIntfID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800635 "onu-id": sq.onuID,
636 "uni-id": sq.uniID,
637 "uni-port": sq.uniPort,
638 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400639
Girish Gowdraf3728b12022-02-02 21:46:51 -0800640 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
641 if err != nil {
642 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
643 log.Fields{
644 "intf-id": sq.intfID,
645 "direction": sq.direction,
646 "device-id": f.deviceHandler.device.Id}, err)
647 }
648
bseenivaa1622112025-12-11 18:24:02 +0530649 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
650 defer cancel()
651 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(subCtx,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800652 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530653 NetworkIntfId: sq.nniIntfID,
654 UniId: sq.uniID, PortNo: sq.uniPort,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800655 TrafficQueues: TrafficQueues,
656 TechProfileId: sq.tpID}); err != nil {
657 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
658 log.Fields{
659 "intf-id": sq.intfID,
660 "traffic-queues": TrafficQueues,
661 "device-id": f.deviceHandler.device.Id}, err)
662 }
663 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
664
665 return err
666}
667
668// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
669func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400670 var Direction string
671 var SchedCfg *tp_pb.SchedulerConfig
672 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800673 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530674 log.Fields{
675 "direction": sq.direction,
676 "intf-id": sq.intfID,
677 "onu-id": sq.onuID,
678 "uni-id": sq.uniID,
679 "uni-port": sq.uniPort,
680 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530681 switch sq.direction {
682 case tp_pb.Direction_UPSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700683 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400684 Direction = "upstream"
mgouda86543582025-10-29 20:58:16 +0530685 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700686 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400687 Direction = "downstream"
688 }
689
Girish Gowdraa482f272021-03-24 23:04:19 -0700690 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 -0400691
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700692 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)}
Gamze Abaka78a1d2a2020-04-27 10:17:27 +0000693 TrafficSched[0].TechProfileId = sq.tpID
Girish Kumar8f73fe02019-12-09 13:19:37 +0000694
bseenivaa1622112025-12-11 18:24:02 +0530695 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
696 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800697 IntfId: sq.intfID, OnuId: sq.onuID,
698 UniId: sq.uniID, PortNo: sq.uniPort,
699 TrafficScheds: TrafficSched}); err != nil {
bseenivaa1622112025-12-11 18:24:02 +0530700 cancel()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800701 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530702 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800703 "intf-id": sq.intfID,
704 "traffic-schedulers": TrafficSched,
705 "onu-id": sq.onuID,
706 "uni-id": sq.uniID,
707 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000708 }
bseenivaa1622112025-12-11 18:24:02 +0530709 cancel()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800710 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
711 log.Fields{"device-id": f.deviceHandler.device.Id,
712 "intf-id": sq.intfID,
713 "onu-id": sq.onuID,
714 "uni-id": sq.uniID,
715 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400716
Girish Gowdraf3728b12022-02-02 21:46:51 -0800717 if sq.direction == tp_pb.Direction_UPSTREAM {
718 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
719 // Delete the TCONT on the ONU.
720 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000721 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Akash Kankanala041a2122024-10-16 15:49:22 +0530722 if err = f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800723 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000724 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800725 "intf": sq.intfID,
726 "onu-id": sq.onuID,
727 "uni-id": sq.uniID,
728 "device-id": f.deviceHandler.device.Id,
729 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000730 }
731 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000732
733 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400734 * delete the meter id on the KV store.
735 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800736 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400737 return err
738}
739
Girish Gowdra197acc12021-08-16 10:59:45 -0700740// We are trying to force remove the schedulers and queues here if one exists for the given key.
741// We ignore any errors encountered in the process. The errors most likely are encountered when
742// the schedulers and queues are already cleared for the given key.
743func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
Girish Gowdra197acc12021-08-16 10:59:45 -0700744 var schedCfg *tp_pb.SchedulerConfig
Girish Gowdra197acc12021-08-16 10:59:45 -0700745 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
746 log.Fields{
747 "direction": sq.direction,
748 "intf-id": sq.intfID,
749 "onu-id": sq.onuID,
750 "uni-id": sq.uniID,
751 "uni-port": sq.uniPort,
752 "tp-id": sq.tpID,
753 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530754 switch sq.direction {
755 case tp_pb.Direction_UPSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700756 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
mgouda86543582025-10-29 20:58:16 +0530757 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700758 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
759 }
760
761 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
762 TrafficSched := []*tp_pb.TrafficScheduler{f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)}
763 TrafficSched[0].TechProfileId = sq.tpID
764
765 // Remove traffic queues. Ignore any errors, just log them.
766 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
767 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
768 "direction": sq.direction,
769 "intf-id": sq.intfID,
770 "onu-id": sq.onuID,
771 "uni-id": sq.uniID,
772 "uni-port": sq.uniPort,
773 "tp-id": sq.tpID,
774 "device-id": f.deviceHandler.device.Id,
775 "err": err})
776 } else {
bseenivaa1622112025-12-11 18:24:02 +0530777 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
778 if _, err := f.deviceHandler.Client.RemoveTrafficQueues(subCtx,
Girish Gowdra197acc12021-08-16 10:59:45 -0700779 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
780 UniId: sq.uniID, PortNo: sq.uniPort,
781 TrafficQueues: TrafficQueues,
782 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
783 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
784 "direction": sq.direction,
785 "intf-id": sq.intfID,
786 "onu-id": sq.onuID,
787 "uni-id": sq.uniID,
788 "uni-port": sq.uniPort,
789 "tp-id": sq.tpID,
790 "device-id": f.deviceHandler.device.Id,
791 "err": err})
Girish Gowdra197acc12021-08-16 10:59:45 -0700792 } else {
793 logger.Infow(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
794 "direction": sq.direction,
795 "intf-id": sq.intfID,
796 "onu-id": sq.onuID,
797 "uni-id": sq.uniID,
798 "uni-port": sq.uniPort,
799 "tp-id": sq.tpID})
800 }
bseenivaa1622112025-12-11 18:24:02 +0530801 cancel()
Girish Gowdra197acc12021-08-16 10:59:45 -0700802 }
803
bseenivaa1622112025-12-11 18:24:02 +0530804 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
Girish Gowdra197acc12021-08-16 10:59:45 -0700805 // Remove traffic schedulers. Ignore any errors, just log them.
bseenivaa1622112025-12-11 18:24:02 +0530806 if _, err := f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Girish Gowdra197acc12021-08-16 10:59:45 -0700807 IntfId: sq.intfID, OnuId: sq.onuID,
808 UniId: sq.uniID, PortNo: sq.uniPort,
809 TrafficScheds: TrafficSched}); err != nil {
810 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
811 "direction": sq.direction,
812 "intf-id": sq.intfID,
813 "onu-id": sq.onuID,
814 "uni-id": sq.uniID,
815 "uni-port": sq.uniPort,
816 "tp-id": sq.tpID,
817 "device-id": f.deviceHandler.device.Id,
818 "err": err})
819 } else {
820 logger.Infow(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
821 "direction": sq.direction,
822 "intf-id": sq.intfID,
823 "onu-id": sq.onuID,
824 "uni-id": sq.uniID,
825 "uni-port": sq.uniPort,
826 "tp-id": sq.tpID})
827 }
bseenivaa1622112025-12-11 18:24:02 +0530828 cancel()
Girish Gowdra197acc12021-08-16 10:59:45 -0700829}
830
Gamze Abakafee36392019-10-03 11:17:24 +0000831// This function allocates tconts and GEM ports for an ONU
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530832func (f *OpenOltFlowMgr) createTcontGemports(ctx context.Context, intfID uint32, nniIntfID 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 +0000833 var allocIDs []uint32
834 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530835 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530836 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000837 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000838 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
839 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
840 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530841
Neha Sharma96b7bf22020-06-15 10:37:32 +0000842 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530843 "intf-id": intfID,
844 "onu-id": onuID,
845 "uni-id": uniID,
846 "device-id": f.deviceHandler.device.Id,
847 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530848
Manikkaraj kb1d51442019-07-23 10:41:02 -0400849 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700850 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000851 if techProfileInstance == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000852 logger.Infow(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530853 log.Fields{
854 "path": tpPath,
855 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700856 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000857 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530858 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000859 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530860 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700861 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530862 "tp-id": TpID,
863 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000864 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530865 }
yasin saplibddc2d72022-02-08 13:10:17 +0000866 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700867 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400868 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530869 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000870 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530871 log.Fields{
872 "uni": uni,
873 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530874 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530875 }
Gamze Abakafee36392019-10-03 11:17:24 +0000876
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700877 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700878 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700879 if UsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530880 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700881 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
882 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000883 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700885 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700886 "onu-id": onuID,
887 "uni-id": uniID,
888 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700889 "meter-id": UsMeterID,
890 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000891 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700892 return 0, nil, nil
893 }
894 }
895 if DsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530896 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700897 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
898 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000899 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700901 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700902 "onu-id": onuID,
903 "uni-id": uniID,
904 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700905 "meter-id": DsMeterID,
906 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000907 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700908 return 0, nil, nil
909 }
910 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700911 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700912 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700913 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700914 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700915 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000916
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 if tpInstanceExists {
918 return allocID, gemPortIDs, techProfileInstance
919 }
920
921 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700922 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700923 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000924 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700925 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700926 "intf-id": intfID,
927 "onu-id": onuID,
928 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700929 "alloc-ids": allocIDs,
930 "gemports": allgemPortIDs,
931 "device-id": f.deviceHandler.device.Id})
932 // Send Tconts and GEM ports to KV store
933 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530934 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400935 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700936 // CreateSchedulerQueues for EPON needs to be implemented here
937 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700938 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700939 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700940 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700941 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700942 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700943
944 if tpInstanceExists {
945 return allocID, gemPortIDs, techProfileInstance
946 }
947
948 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700949 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700950 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000951 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700952 log.Fields{
953 "alloc-ids": allocIDs,
954 "gemports": allgemPortIDs,
955 "device-id": f.deviceHandler.device.Id})
956 // Send Tconts and GEM ports to KV store
957 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
958 return allocID, gemPortIDs, techProfileInstance
959 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000960 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700961 log.Fields{
962 "tpInst": tpInst})
963 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530964 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530965}
966
npujarec5762e2020-01-01 14:08:48 +0530967func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000968 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530969 log.Fields{
970 "intf-id": intfID,
971 "onu-id": onuID,
972 "uni-id": uniID,
973 "alloc-id": allocID,
974 "gemport-ids": gemPortIDs,
975 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530976 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000977 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000978 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 +0530979 }
yasin saplibddc2d72022-02-08 13:10:17 +0000980 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000981 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 +0530982 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700983
Neha Sharma96b7bf22020-06-15 10:37:32 +0000984 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 -0400985 for _, gemPort := range gemPortIDs {
yasin saplibddc2d72022-02-08 13:10:17 +0000986 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPort); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000987 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPort})
988 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400989 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530990}
991
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700992func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530993 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000994 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700995 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
996 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530997 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700998 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
999 if err != nil || f.techprofile == nil {
1000 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
1001 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
1002 }
1003 logger.Debugw(ctx, "init-tech-profile-done",
1004 log.Fields{
1005 "intf-id": intfID,
1006 "device-id": f.deviceHandler.device.Id})
1007 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -07001008 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301009 }
1010 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001011 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
1012 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 +05301013}
1014
Gamze Abaka7650be62021-02-26 10:50:36 +00001015func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001016 flowContext.classifier[PacketTagType] = SingleTag
1017 // extract the cvid/inner-vid from the write metadata
1018 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1019 if writeMetadata != 0 {
1020 // Writemetadata field is 8 bytes
1021 // cvid is on the outer most two bytes of the write metadata
1022 cvid := (writeMetadata & 0xffff000000000000) >> 48
1023 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
1024 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
1025 flowContext.classifier[PacketTagType] = DoubleTag
1026 }
1027 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001028 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301029 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001030 "uplinkClassifier": flowContext.classifier,
1031 "uplinkAction": flowContext.action})
1032 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301033}
1034
Gamze Abaka7650be62021-02-26 10:50:36 +00001035func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1036 downlinkClassifier := flowContext.classifier
1037 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001038 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1039 downlinkClassifier[PacketTagType] = SingleTag
1040 // extract the cvid/inner-vid from the write metadata
1041 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1042 if writeMetadata != 0 {
1043 // Writemetadata field is 8 bytes
1044 // cvid is on the outer most two bytes of the write metadata
1045 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1046 downlinkClassifier[PacketTagType] = DoubleTag
1047 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301048 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001049 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301050 log.Fields{
1051 "downlinkClassifier": downlinkClassifier,
1052 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001053
Girish Gowdraffa52e52022-02-16 15:48:10 -08001054 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1055 // The matched vlan is the one that is getting popped.
1056 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1057 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1058 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1059 if ok {
1060 downlinkAction[VlanVid] = dlClVid & 0xfff
1061 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301062 }
1063
Gamze Abaka7650be62021-02-26 10:50:36 +00001064 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301065}
1066
Gamze Abaka7650be62021-02-26 10:50:36 +00001067func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001068 intfID := flowContext.intfID
1069 onuID := flowContext.onuID
1070 uniID := flowContext.uniID
1071 classifier := flowContext.classifier
1072 action := flowContext.action
1073 allocID := flowContext.allocID
1074 gemPortID := flowContext.gemPortID
1075 tpID := flowContext.tpID
1076 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001077 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301078 log.Fields{
1079 "intf-id": intfID,
1080 "onu-id": onuID,
1081 "uni-id": uniID,
1082 "device-id": f.deviceHandler.device.Id,
1083 "classifier": classifier,
1084 "action": action,
1085 "direction": direction,
1086 "alloc-id": allocID,
1087 "gemport-id": gemPortID,
1088 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001089
yasin saplibddc2d72022-02-08 13:10:17 +00001090 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001091 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001092 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301093 log.Fields{
1094 "device-id": f.deviceHandler.device.Id,
1095 "intf-id": intfID,
1096 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001097 return nil
yasin saplid0566272021-12-21 09:10:30 +00001098 } else if err != nil {
1099 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1100 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1101 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301102 }
yasin saplid0566272021-12-21 09:10:30 +00001103
David K. Bainbridge794735f2020-02-11 21:01:37 -08001104 classifierProto, err := makeOpenOltClassifierField(classifier)
1105 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301106 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301107 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001108 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301109 log.Fields{
1110 "classifier": *classifierProto,
1111 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001112 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001113 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301114 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301115 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001116 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301117 log.Fields{
1118 "action": *actionProto,
1119 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001120 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301121 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301122 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001123 log.Fields{
1124 "classifier": classifier,
1125 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301126 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001127 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301128 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001129
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001130 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001131 OnuId: int32(onuID),
1132 UniId: int32(uniID),
1133 FlowId: logicalFlow.Id,
1134 FlowType: direction,
1135 AllocId: int32(allocID),
1136 NetworkIntfId: int32(networkIntfID),
1137 GemportId: int32(gemPortID),
1138 Classifier: classifierProto,
1139 Action: actionProto,
1140 Priority: int32(logicalFlow.Priority),
1141 Cookie: logicalFlow.Cookie,
1142 PortNo: flowContext.portNo,
1143 TechProfileId: tpID,
1144 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1145 PbitToGemport: flowContext.pbitToGem,
1146 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001147 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001148 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001149 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001151 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301152 log.Fields{"direction": direction,
1153 "device-id": f.deviceHandler.device.Id,
1154 "flow": flow,
1155 "intf-id": intfID,
1156 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001157
David K. Bainbridge794735f2020-02-11 21:01:37 -08001158 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301159}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001160
Gamze Abaka7650be62021-02-26 10:50:36 +00001161func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001162 intfID := flowContext.intfID
1163 onuID := flowContext.onuID
1164 uniID := flowContext.uniID
1165 logicalFlow := flowContext.logicalFlow
1166 classifier := flowContext.classifier
1167 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301168
Neha Sharma96b7bf22020-06-15 10:37:32 +00001169 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301170 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301171 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001172 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301173 "action": action,
1174 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001175 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301176 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301177
1178 // Clear the action map
1179 for k := range action {
1180 delete(action, k)
1181 }
1182
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001183 action[TrapToHost] = true
1184 classifier[UDPSrc] = uint32(68)
1185 classifier[UDPDst] = uint32(67)
1186 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301187
yasin saplibddc2d72022-02-08 13:10:17 +00001188 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001189 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001190 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301191 log.Fields{
1192 "device-id": f.deviceHandler.device.Id,
1193 "intf-id": intfID,
1194 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001195 return nil
yasin saplid0566272021-12-21 09:10:30 +00001196 } else if err != nil {
1197 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1198 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1199 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301200 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301201
Neha Sharma96b7bf22020-06-15 10:37:32 +00001202 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301203 log.Fields{
1204 "ul_classifier": classifier,
1205 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001206 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301207 "intf-id": intfID,
1208 "onu-id": onuID,
1209 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301210
David K. Bainbridge794735f2020-02-11 21:01:37 -08001211 classifierProto, err := makeOpenOltClassifierField(classifier)
1212 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301213 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301214 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001215 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001216 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001217 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301218 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301219 }
1220
David K. Bainbridge794735f2020-02-11 21:01:37 -08001221 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001222 OnuId: int32(onuID),
1223 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001224 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001225 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001226 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001227 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001228 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301229 Classifier: classifierProto,
1230 Action: actionProto,
1231 Priority: int32(logicalFlow.Priority),
1232 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001233 PortNo: flowContext.portNo,
1234 TechProfileId: flowContext.tpID,
1235 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1236 PbitToGemport: flowContext.pbitToGem,
1237 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001238 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001240 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001241 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001242 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301243 log.Fields{
1244 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001245 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301246 "intf-id": intfID,
1247 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301248
David K. Bainbridge794735f2020-02-11 21:01:37 -08001249 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301250}
1251
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001252// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001253func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1254 delete(flowContext.classifier, VlanVid)
1255 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001256}
1257
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001258// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001259func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001260 intfID := flowContext.intfID
1261 onuID := flowContext.onuID
1262 uniID := flowContext.uniID
1263 logicalFlow := flowContext.logicalFlow
1264 classifier := flowContext.classifier
1265 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266
Neha Sharma96b7bf22020-06-15 10:37:32 +00001267 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001268 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301269 return olterrors.NewErrNotFound("nni-interface-id",
1270 log.Fields{
1271 "classifier": classifier,
1272 "action": action,
1273 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001274 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001275 }
1276
1277 // Clear the action map
1278 for k := range action {
1279 delete(action, k)
1280 }
1281
1282 action[TrapToHost] = true
1283 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001284
yasin saplibddc2d72022-02-08 13:10:17 +00001285 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001286 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001287 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001288 return nil
yasin saplid0566272021-12-21 09:10:30 +00001289 } else if err != nil {
1290 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1291 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1292 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001293 }
1294
Neha Sharma96b7bf22020-06-15 10:37:32 +00001295 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301296 log.Fields{
1297 "ul_classifier": classifier,
1298 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001299 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301300 "device-id": f.deviceHandler.device.Id,
1301 "intf-id": intfID,
1302 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001303
David K. Bainbridge794735f2020-02-11 21:01:37 -08001304 classifierProto, err := makeOpenOltClassifierField(classifier)
1305 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301306 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001307 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001308 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301309 log.Fields{
1310 "classifier": *classifierProto,
1311 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001312 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001313 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301314 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001315 }
1316
David K. Bainbridge794735f2020-02-11 21:01:37 -08001317 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001318 OnuId: int32(onuID),
1319 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001320 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001321 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001322 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001323 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001324 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001325 Classifier: classifierProto,
1326 Action: actionProto,
1327 Priority: int32(logicalFlow.Priority),
1328 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001329 PortNo: flowContext.portNo,
1330 TechProfileId: flowContext.tpID,
1331 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1332 PbitToGemport: flowContext.pbitToGem,
1333 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001334 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001335
David K. Bainbridge794735f2020-02-11 21:01:37 -08001336 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001337 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 -08001338 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001339
David K. Bainbridge794735f2020-02-11 21:01:37 -08001340 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001341}
1342
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001343// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001344func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1345 intfID := flowContext.intfID
1346 onuID := flowContext.onuID
1347 uniID := flowContext.uniID
1348 portNo := flowContext.portNo
1349 allocID := flowContext.allocID
1350 gemPortID := flowContext.gemPortID
1351 logicalFlow := flowContext.logicalFlow
1352 classifier := flowContext.classifier
1353 action := flowContext.action
1354
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001355 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301356 log.Fields{
1357 "intf-id": intfID,
1358 "onu-id": onuID,
1359 "port-no": portNo,
1360 "alloc-id": allocID,
1361 "gemport-id": gemPortID,
1362 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001363 "flow": logicalFlow,
1364 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301365
1366 uplinkClassifier := make(map[string]interface{})
1367 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301368
manikkaraj kbf256be2019-03-25 00:13:48 +05301369 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001370 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001371 uplinkClassifier[PacketTagType] = SingleTag
1372 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001373 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301374 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001375 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001376 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001377 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001378 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301379 "device-id": f.deviceHandler.device.Id,
1380 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001381 "intf-id": intfID,
1382 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001383 return nil
yasin saplid0566272021-12-21 09:10:30 +00001384 } else if err != nil {
1385 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1386 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1387 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301388 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301389 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001390 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301391 log.Fields{
1392 "ul_classifier": uplinkClassifier,
1393 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001394 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301395 "device-id": f.deviceHandler.device.Id,
1396 "intf-id": intfID,
1397 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301398
David K. Bainbridge794735f2020-02-11 21:01:37 -08001399 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1400 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301401 return olterrors.NewErrInvalidValue(log.Fields{
1402 "classifier": uplinkClassifier,
1403 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301404 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001405 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301406 log.Fields{
1407 "classifier": *classifierProto,
1408 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001409 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001410 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301411 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301412 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001413 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301414 log.Fields{
1415 "action": *actionProto,
1416 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001417 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301418 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301419 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001420 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301421 "action": action,
1422 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001423 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301424 }
1425
David K. Bainbridge794735f2020-02-11 21:01:37 -08001426 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001427 OnuId: int32(onuID),
1428 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001429 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001430 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001431 AllocId: int32(allocID),
1432 NetworkIntfId: int32(networkIntfID),
1433 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301434 Classifier: classifierProto,
1435 Action: actionProto,
1436 Priority: int32(logicalFlow.Priority),
1437 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001438 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001439 TechProfileId: flowContext.tpID,
1440 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1441 PbitToGemport: flowContext.pbitToGem,
1442 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001443 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001444 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001445 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001446 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001447 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301448 log.Fields{
1449 "device-id": f.deviceHandler.device.Id,
1450 "onu-id": onuID,
1451 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001452 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301453 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001454
David K. Bainbridge794735f2020-02-11 21:01:37 -08001455 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301456}
1457
David K. Bainbridge794735f2020-02-11 21:01:37 -08001458func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001459 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001460
1461 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1462 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1463 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001464 if vlanID != ReservedVlan {
1465 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001466 classifier.OVid = vid
1467 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301468 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001469 // The classifierInfo[Metadata] is set for the following flows
1470 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1471 // - Mcast flow that points to a group in the treatment
1472 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1473 // - inner vid for a double tagged packet in the datapath flow
1474 // - outer vid for a single tagged packet in the datapath flow
1475 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001476 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1477 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301478 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1479 // If OLT is using transparent tag mechanism, then it classifies whatever tag it sees to/from ONU which
Akash Kankanala041a2122024-10-16 15:49:22 +05301480 // is OVid from the perspective of the OLT. When OLT also places or pops the outer tag, then classifierInfo[Metadata]
Andrea Campanellafaa42152021-10-28 11:50:56 +05301481 // becomes the IVid.
1482 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1483 if vid != ReservedVlan {
1484 classifier.IVid = vid
1485 }
1486 } else {
1487 if vid != ReservedVlan {
1488 classifier.OVid = vid
1489 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001490 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301491 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301492 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001493 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301494 classifier.OPbits = vlanPcp
1495 } else {
1496 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301497 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001498 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1499 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1500 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1501 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001502 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001503 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001504 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1505 classifier.PktTagType = pktTagType
1506
1507 switch pktTagType {
1508 case SingleTag:
1509 case DoubleTag:
1510 case Untagged:
1511 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001512 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301513 }
1514 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001515 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301516}
1517
Akash Kankanala041a2122024-10-16 15:49:22 +05301518// nolint: unparam
1519// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001520func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001521 var actionCmd openoltpb2.ActionCmd
1522 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301523 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001524 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001525 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301526 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001527 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001528 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001529 action.Cmd.RemarkInnerPbits = true
1530 action.IPbits = actionInfo[VlanPcp].(uint32)
1531 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001532 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001533 action.Cmd.TranslateInnerTag = true
1534 action.IVid = actionInfo[VlanVid].(uint32)
1535 }
1536 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001538 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001539 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301540 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001541 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001542 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001543 action.OPbits = actionInfo[VlanPcp].(uint32)
1544 action.Cmd.RemarkOuterPbits = true
1545 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001546 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001547 action.IVid = classifierInfo[VlanVid].(uint32)
1548 action.Cmd.TranslateInnerTag = true
1549 }
1550 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001551 } else if _, ok := actionInfo[TrapToHost]; ok {
1552 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001553 } else if _, ok := actionInfo[VlanVid]; ok {
1554 // Translate outer vid
1555 action.Cmd.TranslateOuterTag = true
1556 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301557 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301558 // When OLT is transparent to vlans no-action is valid.
1559 /*
1560 else {
1561 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1562 }
1563 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001564 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301565}
1566
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001567// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001568func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001569 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301570}
1571
Gamze Abakafee36392019-10-03 11:17:24 +00001572// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001573// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1574// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1575// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1576// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1577// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1578// because it was observed that if the ONU device was deleted too soon after the flows were
1579// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1580// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1581// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001582func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001583 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001584 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1585
Gamze Abakafee36392019-10-03 11:17:24 +00001586 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001587 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001588 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001589 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001590 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001591 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1592 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1593 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1594 log.Fields{
1595 "tp-id": tpID,
1596 "path": tpPath})
1597 }
1598 switch tpInstance := tpInst.(type) {
1599 case *tp_pb.TechProfileInstance:
1600 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1601 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1602 }
1603 // Force cleanup scheduler/queues -- end
1604
1605 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301606 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001607 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301608 // return err
1609 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001610 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001611 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 +00001612 }
1613 return nil
1614}
1615
1616// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301617func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001618 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001619 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001620 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001621 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301622 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1623 log.Fields{
1624 "tp-id": tpID,
1625 "uni-port-name": uniPortName,
1626 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001627 }
1628 return nil
1629}
1630
David K. Bainbridge794735f2020-02-11 21:01:37 -08001631func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001632 var intfID uint32
1633 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1634 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1635 */
1636 if deviceFlow.AccessIntfId != -1 {
1637 intfID = uint32(deviceFlow.AccessIntfId)
1638 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001639 // We need to log the valid interface ID.
1640 // 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 +00001641 intfID = uint32(deviceFlow.NetworkIntfId)
1642 }
1643
Neha Sharma96b7bf22020-06-15 10:37:32 +00001644 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301645 "flow": *deviceFlow,
1646 "device-id": f.deviceHandler.device.Id,
1647 "intf-id": intfID})
bseenivaa1622112025-12-11 18:24:02 +05301648 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1649 _, err := f.deviceHandler.Client.FlowAdd(subCtx, deviceFlow)
1650 cancel()
Daniele Rossi22db98e2019-07-11 11:50:00 +00001651
1652 st, _ := status.FromError(err)
1653 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001654 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001655 "err": err,
1656 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301657 "device-id": f.deviceHandler.device.Id,
1658 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001659 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301660 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001661
1662 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001663 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301664 log.Fields{"err": err,
1665 "device-flow": deviceFlow,
1666 "device-id": f.deviceHandler.device.Id,
1667 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001668 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001669 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001670 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301671 log.Fields{
1672 "flow": *deviceFlow,
1673 "device-id": f.deviceHandler.device.Id,
1674 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001675
yasin saplid0566272021-12-21 09:10:30 +00001676 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1677 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1678 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001679 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001680 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001681}
1682
Neha Sharma96b7bf22020-06-15 10:37:32 +00001683func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1684 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301685 log.Fields{
1686 "flow": *deviceFlow,
1687 "device-id": f.deviceHandler.device.Id})
bseenivaa1622112025-12-11 18:24:02 +05301688 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1689 _, err := f.deviceHandler.Client.FlowRemove(subCtx, deviceFlow)
1690 cancel()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001691 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001692 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001693 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301694 log.Fields{
1695 "err": err,
1696 "deviceFlow": deviceFlow,
1697 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301698 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001699 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001700 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001701 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001702 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001703 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001704 "of-flow-id": ofFlowID,
1705 "flow": *deviceFlow,
1706 "device-id": f.deviceHandler.device.Id,
1707 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001708 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301709}
1710
David K. Bainbridge794735f2020-02-11 21:01:37 -08001711func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001712 classifierInfo := make(map[string]interface{})
1713 actionInfo := make(map[string]interface{})
1714
1715 classifierInfo[EthType] = uint32(LldpEthType)
1716 classifierInfo[PacketTagType] = Untagged
1717 actionInfo[TrapToHost] = true
1718
1719 // LLDP flow is installed to trap LLDP packets on the NNI port.
1720 // We manage flow_id resource pool on per PON port basis.
1721 // Since this situation is tricky, as a hack, we pass the NNI port
1722 // index (network_intf_id) as PON port Index for the flow_id resource
1723 // pool. Also, there is no ONU Id available for trapping LLDP packets
1724 // on NNI port, use onu_id as -1 (invalid)
1725 // ****************** CAVEAT *******************
1726 // This logic works if the NNI Port Id falls within the same valid
1727 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1728 // we need to have a re-look at this.
1729 // *********************************************
1730
1731 var onuID = -1
1732 var uniID = -1
1733 var gemPortID = -1
1734
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001735 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301737 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001738 }
yasin saplibddc2d72022-02-08 13:10:17 +00001739 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001740 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001741 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001742 return nil
yasin saplid0566272021-12-21 09:10:30 +00001743 } else if err != nil {
1744 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1745 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1746 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001747 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001748
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1750 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301751 return olterrors.NewErrInvalidValue(
1752 log.Fields{
1753 "classifier": classifierInfo,
1754 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001755 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001756 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301757 log.Fields{
1758 "classifier": *classifierProto,
1759 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001760 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001761 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301762 return olterrors.NewErrInvalidValue(
1763 log.Fields{
1764 "action": actionInfo,
1765 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001766 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001767 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301768 log.Fields{
1769 "action": *actionProto,
1770 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001771
1772 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1773 OnuId: int32(onuID), // OnuId not required
1774 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001775 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001776 FlowType: Downstream,
1777 NetworkIntfId: int32(networkInterfaceID),
1778 GemportId: int32(gemPortID),
1779 Classifier: classifierProto,
1780 Action: actionProto,
1781 Priority: int32(flow.Priority),
1782 Cookie: flow.Cookie,
1783 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001784 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001785 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301786 log.Fields{
1787 "flow": downstreamflow,
1788 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001789 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001790 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301791 log.Fields{
1792 "device-id": f.deviceHandler.device.Id,
1793 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001794 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001795
David K. Bainbridge794735f2020-02-11 21:01:37 -08001796 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301797}
1798
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001799func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1800 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001801}
1802
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001803// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001804func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001805 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1806 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1807 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001808 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301809 log.Fields{
1810 "intf-id": intfID,
1811 "onu-id": onuID,
1812 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001813 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001814 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301815 return nil, olterrors.NewErrNotFound("onu-child-device",
1816 log.Fields{
1817 "onu-id": onuID,
1818 "intf-id": intfID,
1819 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001820 }
khenaidoo106c61a2021-08-11 18:05:46 -04001821 onuDev = NewOnuDevice(onuDevice.Id, onuDevice.Type, onuDevice.SerialNumber, onuDevice.ProxyAddress.OnuId, onuDevice.ProxyAddress.ChannelId, onuDevice.ProxyAddress.DeviceId, false, onuDevice.AdapterEndpoint)
Akash Kankanala041a2122024-10-16 15:49:22 +05301822 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001823 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1824 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001825 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301826 log.Fields{
1827 "intf-id": intfID,
1828 "onu-id": onuID,
1829 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001830 }
1831
1832 return onuDev.(*OnuDevice), nil
1833}
1834
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001835// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001836func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1837 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301838 log.Fields{
1839 "pon-port": intfID,
1840 "onu-id": onuID,
1841 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001842 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001843 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001844 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301845 return nil, olterrors.NewErrNotFound("onu",
1846 log.Fields{
1847 "interface-id": parentPortNo,
1848 "onu-id": onuID,
1849 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001850 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301851 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001852 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301853 log.Fields{
1854 "device-id": f.deviceHandler.device.Id,
1855 "child_device_id": onuDevice.Id,
1856 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301857 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301858}
1859
Neha Sharma96b7bf22020-06-15 10:37:32 +00001860func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1861 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301862 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001863 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301864 log.Fields{
1865 "intf-id": intfID,
1866 "onu-id": onuID,
1867 "uni-id": uniID,
1868 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001869 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301870 }
1871
khenaidoodc2116e2021-10-19 17:33:19 -04001872 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001873 DeviceId: onuDev.deviceID,
1874 UniId: uniID,
1875 TpInstancePath: tpPath,
1876 GemPortId: gemPortID,
1877 }
1878 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1879
1880 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301881 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1882 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001883 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1884 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301885 "onu-id": onuDev.deviceID,
1886 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001887 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301888 }
khenaidoo106c61a2021-08-11 18:05:46 -04001889
Neha Sharma96b7bf22020-06-15 10:37:32 +00001890 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301891 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001892 "msg": delGemPortMsg,
1893 "from-adapter": f.deviceHandler.device.Type,
1894 "to-adapter": onuDev.deviceType,
1895 "device-id": f.deviceHandler.device.Id,
1896 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301897 return nil
1898}
1899
Neha Sharma96b7bf22020-06-15 10:37:32 +00001900func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1901 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301902 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001903 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301904 log.Fields{
1905 "intf-id": intfID,
1906 "onu-id": onuID,
1907 "uni-id": uniID,
1908 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001909 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301910 }
1911
khenaidoodc2116e2021-10-19 17:33:19 -04001912 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001913 DeviceId: onuDev.deviceID,
1914 UniId: uniID,
1915 TpInstancePath: tpPath,
1916 AllocId: allocID,
1917 }
1918
Neha Sharma96b7bf22020-06-15 10:37:32 +00001919 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301920 log.Fields{
1921 "msg": *delTcontMsg,
1922 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001923
1924 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301925 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1926 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001927 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1928 "to-adapter": onuDev.adapterEndpoint,
1929 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301930 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001931 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301932 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001933 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301934 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001935 "msg": delTcontMsg,
1936 "device-id": f.deviceHandler.device.Id,
1937 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301938 return nil
1939}
1940
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001941// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001942// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001943func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05301944 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool, nniIntfID uint32) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001945 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001946
Girish Gowdraa482f272021-03-24 23:04:19 -07001947 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001948 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001949 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1950 log.Fields{
1951 "tpPath": tpPath,
1952 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001953
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001954 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001955 if err != nil || techprofileInst == nil {
1956 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1957 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1958 if childDevice == nil {
1959 // happens when subscriber un-provision is immediately followed by child device delete
1960 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1961 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1962 return nil
1963 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001964 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1965 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001966 log.Fields{
1967 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001968 "path": tpPath}, err).Log()
1969 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001970 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001971
1972 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001973 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001974 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001975 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1976 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001977 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1978 if err != nil {
1979 return err
1980 }
1981 used := false
1982 for _, id := range flowIDs {
1983 if flowID != id {
1984 used = true
1985 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001986 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001987 }
1988 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001989 for i, flowIDinMap := range flowIDs {
1990 if flowIDinMap == flowID {
1991 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001992 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001993 return err
1994 }
1995 break
1996 }
1997 }
1998 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1999 log.Fields{
2000 "gemport-id": gemPortID,
2001 "usedByFlows": flowIDs,
2002 "currentFlow": flowID,
2003 "device-id": f.deviceHandler.device.Id})
2004 allGemPortsFree = false
2005 }
2006 }
2007 if !allGemPortsFree {
2008 return nil
2009 }
2010 }
2011
2012 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 -08002013
2014 // 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 +00002015 switch techprofileInst := techprofileInst.(type) {
2016 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08002017 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2018 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00002019 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08002020
yasin saplibddc2d72022-02-08 13:10:17 +00002021 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002022 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2023 log.Fields{
2024 "err": err,
2025 "intf": intfID,
2026 "onu-id": onuID,
2027 "uni-id": uniID,
2028 "device-id": f.deviceHandler.device.Id,
2029 "gemport-id": gemPortID})
2030 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002031 }
2032 // Remove queues at OLT in upstream and downstream direction
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302033 schedQ := schedQueue{tpInst: techprofileInst, direction: tp_pb.Direction_UPSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum}
Akash Kankanala041a2122024-10-16 15:49:22 +05302034 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002035 logger.Warn(ctx, err)
2036 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302037 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2038 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002039 logger.Warn(ctx, err)
2040 }
2041 }
2042
2043 switch techprofileInst := techprofileInst.(type) {
2044 case *tp_pb.TechProfileInstance:
2045 // 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
Akash Kankanala041a2122024-10-16 15:49:22 +05302046 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2047 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002048 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002049 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002050 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302051 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002052 logger.Warn(ctx, err)
2053 }
2054 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002055 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002056 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002057 } else {
2058 // just remove meter reference for the upstream direction for the current pon/onu/uni
2059 // 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
Akash Kankanala041a2122024-10-16 15:49:22 +05302060 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002061 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002062 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002063 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2064 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002065 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002066 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002067
Girish Gowdraf3728b12022-02-02 21:46:51 -08002068 // Downstream scheduler removal is simple, just invoke RemoveScheduler without all the complex handling we do for the alloc object.
Akash Kankanala041a2122024-10-16 15:49:22 +05302069 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002070 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302071 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002072 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002073 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002074 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002075 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002077 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002078 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302079 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002080 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302081 "onu-id": onuID,
2082 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002083 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002084 "alloc-id": techprofileInst.AllocId,
2085 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002086 }
yasin saplibddc2d72022-02-08 13:10:17 +00002087 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302088 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2089 logger.Warn(ctx, err)
2090 }
2091 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2092 logger.Warn(ctx, err)
2093 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002094 default:
2095 logger.Errorw(ctx, "error-unknown-tech",
2096 log.Fields{
2097 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002098 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002099
2100 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2101 switch techprofileInst := techprofileInst.(type) {
2102 case *tp_pb.TechProfileInstance:
2103 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2104 // Delete the gem port on the ONU.
2105 if sendDeleteGemRequest {
2106 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2107 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2108 log.Fields{
2109 "err": err,
2110 "intfID": intfID,
2111 "onu-id": onuID,
2112 "uni-id": uniID,
2113 "device-id": f.deviceHandler.device.Id,
2114 "gemport-id": gemPort.GemportId})
2115 }
yasin saplibddc2d72022-02-08 13:10:17 +00002116 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002117 }
2118 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302119 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302120 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2121 logger.Warn(ctx, err)
2122 }
2123 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2124 logger.Warn(ctx, err)
2125 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002126 }
2127
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302128 return nil
2129}
2130
David K. Bainbridge794735f2020-02-11 21:01:37 -08002131// nolint: gocyclo
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302132func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string, nni_port uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002133 logger.Infow(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302134 log.Fields{
2135 "flowDirection": flowDirection,
2136 "flow": *flow,
2137 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002138
2139 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002140 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002141 }
2142
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302143 var ethType, ipProto, inPort uint32
2144 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05302145 switch field.Type {
2146 case flows.IP_PROTO:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302147 ipProto = field.GetIpProto()
2148 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
mgouda86543582025-10-29 20:58:16 +05302149 case flows.ETH_TYPE:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302150 ethType = field.GetEthType()
2151 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
mgouda86543582025-10-29 20:58:16 +05302152 case flows.IN_PORT:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302153 inPort = field.GetPort()
2154 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2155 }
2156 }
2157 portType := plt.IntfIDToPortTypeName(inPort)
2158 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2159 (portType == voltha.Port_ETHERNET_NNI) {
2160 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2161 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2162 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2163 // No more processing needed for trap from nni flows.
2164 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302165
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302166 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302167 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002168 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002169 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302170 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002171 onuID := int32(onu)
2172 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002173 tpID, err := getTpIDFromFlow(ctx, flow)
2174 if err != nil {
2175 return olterrors.NewErrNotFound("tp-id",
2176 log.Fields{
2177 "flow": flow,
2178 "intf-id": Intf,
2179 "onu-id": onuID,
2180 "uni-id": uniID,
2181 "device-id": f.deviceHandler.device.Id}, err)
2182 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183
Neha Sharma96b7bf22020-06-15 10:37:32 +00002184 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302185 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002186 "flow-id": flow.Id,
2187 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302188 "onu-id": onuID,
2189 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302190
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002191 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2192 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002193 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2194 return err
2195 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002196
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302197 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true, nni_port); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002198 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2199 "flow-id": flow.Id,
2200 "device-id": f.deviceHandler.device.Id,
2201 "onu-id": onuID,
2202 "intf": Intf,
2203 "err": err,
2204 })
2205 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302206 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002207
Girish Gowdra82c80982021-03-26 16:22:02 -07002208 // 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 +00002209 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002210 return err
2211 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002212 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002213}
2214
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002215// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002216func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
Matteo Scandolof16389e2021-05-18 00:47:08 +00002217 logger.Infow(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302218 var direction string
2219 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002220
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302221 for _, action := range flows.GetActions(flow) {
2222 if action.Type == flows.OUTPUT {
2223 if out := action.GetOutput(); out != nil {
2224 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302226 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002227 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002228 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002229 }
2230 }
2231 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002232
2233 if flows.HasGroup(flow) {
2234 direction = Multicast
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002235 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302236 direction = Upstream
2237 } else {
2238 direction = Downstream
2239 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302240
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302241 var nni_port uint32
2242 if direction == Upstream {
2243 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2244 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2245 }
2246 } else {
2247 classifierInfo := make(map[string]interface{})
2248 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
2249 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2250 }
2251
Girish Gowdracefae192020-03-19 18:14:10 -07002252 // Serialize flow removes on a per subscriber basis
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302253 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction, nni_port)
Girish Gowdracefae192020-03-19 18:14:10 -07002254
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002255 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002256}
2257
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002258// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002259func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002260 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002261 if ethType, ok := classifierInfo[EthType]; ok {
2262 if ethType.(uint32) == IPv4EthType {
2263 if ipProto, ok := classifierInfo[IPProto]; ok {
2264 if ipProto.(uint32) == IgmpProto {
2265 return true
2266 }
2267 }
2268 }
2269 }
2270 }
2271 return false
2272}
2273
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002274// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002275func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002276 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2277 // The device itself is going to be reset as part of deletion. So nothing to be done.
2278 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2279 return nil
2280 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002281 // Step1 : Fill flowControlBlock
2282 // Step2 : Push the flowControlBlock to ONU channel
2283 // Step3 : Wait on response channel for response
2284 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002285 startTime := time.Now()
2286 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002287 errChan := make(chan error)
2288 flowCb := flowControlBlock{
2289 ctx: ctx,
2290 addFlow: addFlow,
2291 flow: flow,
2292 flowMetadata: flowMetadata,
2293 errChan: &errChan,
2294 }
2295 inPort, outPort := getPorts(flow)
2296 var onuID uint32
2297 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002298 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002299 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002300 if f.flowHandlerRoutineActive[onuID] {
2301 // inPort or outPort is InvalidPort for trap-from-nni flows.
2302 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2303 // Send the flowCb on the ONU flow channel
2304 f.incomingFlows[onuID] <- flowCb
2305 // Wait on the channel for flow handlers return value
2306 err := <-errChan
khenaidoo106c61a2021-08-11 18:05:46 -04002307 logger.Infow(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002308 return err
2309 }
2310 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2311 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002312}
2313
2314// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2315// 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 -07002316func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002317 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002318 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002319 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002320 // block on the channel to receive an incoming flow
2321 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002322 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002323 if flowCb.addFlow {
2324 logger.Info(flowCb.ctx, "adding-flow-start")
2325 startTime := time.Now()
2326 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
2327 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2328 // Pass the return value over the return channel
2329 *flowCb.errChan <- err
2330 } else {
2331 logger.Info(flowCb.ctx, "removing-flow-start")
2332 startTime := time.Now()
2333 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
2334 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds()})
2335 // Pass the return value over the return channel
2336 *flowCb.errChan <- err
2337 }
2338 case <-stopHandler:
2339 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2340 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002341 }
2342 }
2343}
2344
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002345// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002346func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002347 for i, v := range f.stopFlowHandlerRoutine {
2348 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002349 select {
2350 case v <- true:
2351 case <-time.After(time.Second * 5):
2352 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2353 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002354 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002355 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002356 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002357 f.stopFlowHandlerRoutine = nil
2358
2359 if f.incomingFlows != nil {
2360 for k := range f.incomingFlows {
2361 if f.incomingFlows[k] != nil {
2362 f.incomingFlows[k] = nil
2363 }
2364 }
2365 f.incomingFlows = nil
2366 }
2367
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002368 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002369 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2370}
2371
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002372// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302373// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002374func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002375 classifierInfo := make(map[string]interface{})
2376 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002377 var UsMeterID uint32
2378 var DsMeterID uint32
2379
Neha Sharma96b7bf22020-06-15 10:37:32 +00002380 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302381 log.Fields{
2382 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002383 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002385
Neha Sharma96b7bf22020-06-15 10:37:32 +00002386 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002387 if err != nil {
2388 // Error logging is already done in the called function
2389 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002390 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302391 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002392
Esin Karamanccb714b2019-11-29 15:02:06 +00002393 if flows.HasGroup(flow) {
2394 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002395 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002396 }
2397
manikkaraj k17652a72019-05-06 09:06:36 -04002398 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002399 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002400 if err != nil {
2401 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002402 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002403 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002404
Neha Sharma96b7bf22020-06-15 10:37:32 +00002405 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302406 log.Fields{
2407 "classifierinfo_inport": classifierInfo[InPort],
2408 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002409 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002410
Humera Kouser94d7a842019-08-25 19:04:32 -04002411 if ethType, ok := classifierInfo[EthType]; ok {
2412 if ethType.(uint32) == LldpEthType {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002413 logger.Info(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002414 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002415 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002416 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002417 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002418 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2419 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2420 }
2421 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002422 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002423 if ipProto, ok := classifierInfo[IPProto]; ok {
2424 if ipProto.(uint32) == IPProtoDhcp {
2425 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302426 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002427 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002428 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002429 }
2430 }
2431 }
2432 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002433 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002434 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002435 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002436 }
A R Karthick1f85b802019-10-11 05:06:05 +00002437
yasin saplibddc2d72022-02-08 13:10:17 +00002438 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002439
Girish Gowdra6071f382021-12-14 12:52:04 +05302440 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002441 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302442 return olterrors.NewErrNotFound("tpid-for-flow",
2443 log.Fields{
2444 "flow": flow,
2445 "intf-id": IntfID,
2446 "onu-id": onuID,
2447 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002448 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002449 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302450 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302451 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302452 "intf-id": intfID,
2453 "onu-id": onuID,
2454 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002455 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002456 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002457 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302458 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2459 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2460 return err
2461 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002462 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002463 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002464 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302465 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2466 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2467 return err
2468 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002469 }
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302470
2471 var nni_port uint32
2472 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2473 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2474 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2475 }
2476 } else {
2477 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2478 }
2479
2480 return f.processAddFlow(ctx, intfID, nni_port, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002481}
Girish Gowdra3d633032019-12-10 16:37:05 +05302482
Esin Karamanccb714b2019-11-29 15:02:06 +00002483// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002484func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302485 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002486 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302487 "classifier-info": classifierInfo,
2488 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002489
Esin Karaman65409d82020-03-18 10:58:18 +00002490 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002491 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002492 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002493 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002494
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002495 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002496
David K. Bainbridge794735f2020-02-11 21:01:37 -08002497 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002498
yasin saplibddc2d72022-02-08 13:10:17 +00002499 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002500 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002501 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002502 return nil
yasin saplid0566272021-12-21 09:10:30 +00002503 } else if err != nil {
2504 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2505 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2506 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002507 }
yasin saplid0566272021-12-21 09:10:30 +00002508
David K. Bainbridge794735f2020-02-11 21:01:37 -08002509 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2510 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002511 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002512 }
2513 groupID := actionInfo[GroupID].(uint32)
2514 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002515 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002516 FlowType: Multicast,
2517 NetworkIntfId: int32(networkInterfaceID),
2518 GroupId: groupID,
2519 Classifier: classifierProto,
2520 Priority: int32(flow.Priority),
2521 Cookie: flow.Cookie}
2522
Kent Hagermane6ff1012020-07-14 15:07:53 -04002523 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002524 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002525 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002526 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302527 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002528 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302529 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002530 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002531 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002532 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302533 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002534 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002535 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002536 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002537 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002538
David K. Bainbridge794735f2020-02-11 21:01:37 -08002539 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002540}
2541
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002542// getNNIInterfaceIDOfMulticastFlow returns associated NNI interface id of the inPort criterion if exists; returns the first NNI interface of the device otherwise
Esin Karaman65409d82020-03-18 10:58:18 +00002543func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2544 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002545 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002546 if err != nil {
2547 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2548 }
2549 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002550 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002551
2552 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2553 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002554}
2555
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002556// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002557func (f *OpenOltFlowMgr) sendTPDownloadMsgToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uni string, TpID uint32, tpInst tp_pb.TechProfileInstance) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302559 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002560 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302561 log.Fields{
2562 "intf-id": intfID,
2563 "onu-id": onuID,
2564 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002565 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302566 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002567 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002568
yasin saplibddc2d72022-02-08 13:10:17 +00002569 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002570 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002571 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002572 UniId: uniID,
2573 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002574 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002575 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002576 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002577
2578 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2579 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302580 return olterrors.NewErrCommunication("send-techprofile-download-request",
2581 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002582 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302583 "to-adapter": onuDev.deviceType,
2584 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002585 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002586 }
nikesh.krishnan81ec7442023-10-31 17:19:34 +05302587 logger.Infow(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302588 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302589}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002590
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002591// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302592func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002593 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002594
mgouda86543582025-10-29 20:58:16 +05302595 switch packetIn.IntfType {
2596 case "pon":
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002597 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002598 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002599 onuID, uniID := packetIn.OnuId, packetIn.UniId
2600 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 +00002601
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002602 if packetIn.PortNo != 0 {
2603 logicalPortNum = packetIn.PortNo
2604 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002605 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002606 }
2607 // 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 +00002608 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
mgouda86543582025-10-29 20:58:16 +05302609 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002610 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002611 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002612
2613 if logger.V(log.DebugLevel) {
2614 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2615 log.Fields{
2616 "logical-port-num": logicalPortNum,
2617 "intf-type": packetIn.IntfType,
2618 "packet": hex.EncodeToString(packetIn.Pkt),
2619 })
2620 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002621 return logicalPortNum, nil
2622}
2623
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002624// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002625func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002626 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002627
2628 ctag, priority, err := getCTagFromPacket(ctx, packet)
2629 if err != nil {
2630 return 0, err
2631 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302632
Esin Karaman7fb80c22020-07-16 14:23:33 +00002633 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002634 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002635 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002636 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002637 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302638 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002639 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302640 log.Fields{
2641 "pktinkey": pktInkey,
2642 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002643
2644 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002645 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302646 // 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 +00002647 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302648 if err == nil {
2649 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002650 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002652 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002653 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302654 log.Fields{
2655 "pktinkey": pktInkey,
2656 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302657 return gemPortID, nil
2658 }
2659 }
Shrey Baid26912972020-04-16 21:02:31 +05302660 return uint32(0), olterrors.NewErrNotFound("gem-port",
2661 log.Fields{
2662 "pktinkey": pktInkey,
2663 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002664}
2665
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002666func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2667 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002668 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002669 classifier[PacketTagType] = DoubleTag
2670 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002671 /* We manage flowId resource pool on per PON port basis.
2672 Since this situation is tricky, as a hack, we pass the NNI port
2673 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002674 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002675 on NNI port, use onu_id as -1 (invalid)
2676 ****************** CAVEAT *******************
2677 This logic works if the NNI Port Id falls within the same valid
2678 range of PON Port Ids. If this doesn't work for some OLT Vendor
2679 we need to have a re-look at this.
2680 *********************************************
2681 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002682 onuID := -1
2683 uniID := -1
2684 gemPortID := -1
2685 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002686 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302687 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302688 return olterrors.NewErrNotFound("nni-intreface-id",
2689 log.Fields{
2690 "classifier": classifier,
2691 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002692 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302693 }
2694
yasin saplibddc2d72022-02-08 13:10:17 +00002695 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002696 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002697 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002698 return nil
yasin saplid0566272021-12-21 09:10:30 +00002699 } else if err != nil {
2700 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2701 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2702 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002703 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002704
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002705 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2706 log.Fields{
2707 "classifier": classifier,
2708 "action": action,
2709 "flowId": logicalFlow.Id,
2710 "intf-id": networkInterfaceID})
2711
David K. Bainbridge794735f2020-02-11 21:01:37 -08002712 classifierProto, err := makeOpenOltClassifierField(classifier)
2713 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002714 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002715 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002716 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002717 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002718 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002719 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002720 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002721 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002722 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2723 OnuId: int32(onuID), // OnuId not required
2724 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002725 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002726 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002727 AllocId: int32(allocID), // AllocId not used
2728 NetworkIntfId: int32(networkInterfaceID),
2729 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002730 Classifier: classifierProto,
2731 Action: actionProto,
2732 Priority: int32(logicalFlow.Priority),
2733 Cookie: logicalFlow.Cookie,
2734 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002735 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002736 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002737 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002738 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002739 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002740}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002741
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002742// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002743func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2744 var packetType string
2745 ovid, ivid := false, false
2746 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2747 vid := vlanID & VlanvIDMask
2748 if vid != ReservedVlan {
2749 ovid = true
2750 }
2751 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002752
2753 // The classifierInfo[Metadata] is set for the following flows
2754 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2755 // - Mcast flow that points to a group in the action/treatment
2756 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2757 // - inner vid for a double tagged packet in the datapath flow
2758 // - outer vid for a single tagged packet in the datapath flow
2759 // - inner vid in the mcast flow that points to a group
2760
2761 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2762 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2763 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2764 // it is to be used with caution elsewhere as it could result in wrong packetType to be returned to the caller.
Esin Karamanae41e2b2019-12-17 18:13:13 +00002765 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2766 vid := uint32(metadata)
2767 if vid != ReservedVlan {
2768 ivid = true
2769 }
2770 }
2771 if ovid && ivid {
2772 packetType = DoubleTag
2773 } else if !ovid && !ivid {
2774 packetType = Untagged
2775 } else {
2776 packetType = SingleTag
2777 }
2778 return packetType
2779}
2780
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002781// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002782func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002783 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002784 action := make(map[string]interface{})
2785 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2786 action[TrapToHost] = true
2787 /* We manage flowId resource pool on per PON port basis.
2788 Since this situation is tricky, as a hack, we pass the NNI port
2789 index (network_intf_id) as PON port Index for the flowId resource
2790 pool. Also, there is no ONU Id available for trapping packets
2791 on NNI port, use onu_id as -1 (invalid)
2792 ****************** CAVEAT *******************
2793 This logic works if the NNI Port Id falls within the same valid
2794 range of PON Port Ids. If this doesn't work for some OLT Vendor
2795 we need to have a re-look at this.
2796 *********************************************
2797 */
2798 onuID := -1
2799 uniID := -1
2800 gemPortID := -1
2801 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002802 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002803 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302804 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002805 "classifier": classifier,
2806 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002807 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002808 }
yasin saplibddc2d72022-02-08 13:10:17 +00002809 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002810 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002811 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002812 return nil
yasin saplid0566272021-12-21 09:10:30 +00002813 } else if err != nil {
2814 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2815 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2816 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002817 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002818
David K. Bainbridge794735f2020-02-11 21:01:37 -08002819 classifierProto, err := makeOpenOltClassifierField(classifier)
2820 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002821 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002822 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002823 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002824 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002825 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002826 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002827 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002828 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002829 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2830 OnuId: int32(onuID), // OnuId not required
2831 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002832 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002833 FlowType: Downstream,
2834 AllocId: int32(allocID), // AllocId not used
2835 NetworkIntfId: int32(networkInterfaceID),
2836 GemportId: int32(gemPortID), // GemportId not used
2837 Classifier: classifierProto,
2838 Action: actionProto,
2839 Priority: int32(logicalFlow.Priority),
2840 Cookie: logicalFlow.Cookie,
2841 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002842 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002843 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002844 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002845 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002846
David K. Bainbridge794735f2020-02-11 21:01:37 -08002847 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002848}
2849
salmansiddiqui7ac62132019-08-22 03:58:50 +00002850func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2851 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302852 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002853 }
mgouda86543582025-10-29 20:58:16 +05302854 switch Dir {
2855 case tp_pb.Direction_UPSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 return "upstream", nil
mgouda86543582025-10-29 20:58:16 +05302857 case tp_pb.Direction_DOWNSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002858 return "downstream", nil
2859 }
2860 return "", nil
2861}
2862
Kent Hagermane6ff1012020-07-14 15:07:53 -04002863// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302864func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002865 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002866 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002867 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002868 intfID := args[IntfID]
2869 onuID := args[OnuID]
2870 uniID := args[UniID]
2871 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002872 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002873 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002874 gemToAes := make(map[uint32]bool)
2875
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002876 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002877 var direction = tp_pb.Direction_UPSTREAM
2878 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002879 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002880 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002881 attributes = TpInst.UpstreamGemPortAttributeList
2882 } else {
2883 attributes = TpInst.DownstreamGemPortAttributeList
2884 direction = tp_pb.Direction_DOWNSTREAM
2885 }
2886 default:
2887 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002888 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002889 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002890
2891 if len(gemPorts) == 1 {
2892 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002893 gemPortID = gemPorts[0]
2894 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002895 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2896 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002897 pBitMap := attributes[idx].PbitMap
2898 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2899 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2900 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002901 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2903 if pbitSet == pbit1 {
2904 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2905 pbitToGem[pcp] = gemID
2906 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002907 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002908 }
2909 }
2910 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002911 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2912 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2913 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002914 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002915 }
2916
Akash Kankanala041a2122024-10-16 15:49:22 +05302917 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002918
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302919 var nni_port uint32
2920 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2921 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2922 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2923 }
2924 } else {
2925 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2926 }
2927
salmansiddiqui7ac62132019-08-22 03:58:50 +00002928 if ipProto, ok := classifierInfo[IPProto]; ok {
mgouda86543582025-10-29 20:58:16 +05302929 switch ipProto.(uint32) {
2930 case IPProtoDhcp:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002931 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002932 "tp-id": tpID,
2933 "alloc-id": allocID,
2934 "intf-id": intfID,
2935 "onu-id": onuID,
2936 "uni-id": uniID,
2937 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302938 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002939 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002940 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002941 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302942 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002943 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002944 }
mgouda86543582025-10-29 20:58:16 +05302945 case IgmpProto:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002946 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302947 log.Fields{
2948 "intf-id": intfID,
2949 "onu-id": onuID,
2950 "uni-id": uniID,
2951 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002953 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002954 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302955 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002956 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002957 }
mgouda86543582025-10-29 20:58:16 +05302958 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002959 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002960 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002961 }
2962 } else if ethType, ok := classifierInfo[EthType]; ok {
mgouda86543582025-10-29 20:58:16 +05302963 switch ethType.(uint32) {
2964 case EapEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002965 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002966 "intf-id": intfID,
2967 "onu-id": onuID,
2968 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002969 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002970 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002971 var vlanID uint32
2972 if val, ok := classifierInfo[VlanVid]; ok {
2973 vlanID = (val.(uint32)) & VlanvIDMask
2974 } else {
2975 vlanID = DefaultMgmtVlan
2976 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002977 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002978 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002979 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302980 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002981 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002982 }
mgouda86543582025-10-29 20:58:16 +05302983 case PPPoEDEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002984 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2985 "tp-id": tpID,
2986 "alloc-id": allocID,
2987 "intf-id": intfID,
2988 "onu-id": onuID,
2989 "uni-id": uniID,
2990 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302991 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002992 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002993 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002994 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302995 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002996 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002997 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002998 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002999 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003000 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003001 "intf-id": intfID,
3002 "onu-id": onuID,
3003 "uni-id": uniID,
3004 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303005 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003006 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003007 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003008 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303009 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003010 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003012 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003014 "intf-id": intfID,
3015 "onu-id": onuID,
3016 "uni-id": uniID,
3017 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303018 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003019 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003020 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003021 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})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303022 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003023 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 }
3025 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003026 return olterrors.NewErrInvalidValue(log.Fields{
3027 "intf-id": intfID,
3028 "onu-id": onuID,
3029 "uni-id": uniID,
3030 "classifier": classifierInfo,
3031 "action": actionInfo,
3032 "flow": flow},
3033 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003034 }
3035 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003036 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003037 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003038 logger.Warn(ctx, err)
3039 }
3040 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003041 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003042}
3043
Gamze Abakacb0e6772021-06-10 08:32:12 +00003044func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003045 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3046 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3047 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 +05303048 for i := 0; i < len(tpInstances); i++ {
3049 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003050 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003051 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003052 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003053 log.Fields{
3054 "device-id": f.deviceHandler.device.Id,
3055 "intfID": sq.intfID,
3056 "onuID": sq.onuID,
3057 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003058 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003059 })
3060 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303061 }
3062 }
3063 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003064 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003065}
3066
Neha Sharma96b7bf22020-06-15 10:37:32 +00003067func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003068 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05303069 switch field.Type {
3070 case flows.ETH_TYPE:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003071 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003072 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303073 case flows.ETH_DST:
Esin Karamanccb714b2019-11-29 15:02:06 +00003074 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003075 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303076 case flows.ETH_SRC:
Girish Gowdraffa52e52022-02-16 15:48:10 -08003077 classifierInfo[EthSrc] = field.GetEthSrc()
3078 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303079 case flows.IP_PROTO:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003080 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003081 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303082 case flows.IN_PORT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003083 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003084 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303085 case flows.VLAN_VID:
Andrea Campanellafaa42152021-10-28 11:50:56 +05303086 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3087 if field.GetVlanVid() != ReservedVlan {
3088 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3089 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3090 }
mgouda86543582025-10-29 20:58:16 +05303091 case flows.VLAN_PCP:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003092 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003093 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303094 case flows.UDP_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003095 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003096 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303097 case flows.UDP_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003098 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003099 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303100 case flows.IPV4_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003101 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003102 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303103 case flows.IPV4_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003104 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003105 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303106 case flows.METADATA:
David K. Bainbridge82efc492019-09-04 09:57:11 -07003107 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003108 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303109 case flows.TUNNEL_ID:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003110 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303112 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003113 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 return
3115 }
3116 }
3117}
3118
Neha Sharma96b7bf22020-06-15 10:37:32 +00003119func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003120 for _, action := range flows.GetActions(flow) {
mgouda86543582025-10-29 20:58:16 +05303121 switch action.Type {
3122 case flows.OUTPUT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003124 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003125 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003127 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 }
mgouda86543582025-10-29 20:58:16 +05303129 case flows.POP_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003130 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003131 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303132 case flows.PUSH_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003133 if out := action.GetPush(); out != nil {
3134 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003135 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003136 } else {
3137 actionInfo[PushVlan] = true
3138 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003139 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303140 log.Fields{
3141 "push-tpid": actionInfo[TPID].(uint32),
3142 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003143 }
3144 }
mgouda86543582025-10-29 20:58:16 +05303145 case flows.SET_FIELD:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 if out := action.GetSetField(); out != nil {
3147 if field := out.GetField(); field != nil {
3148 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003149 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003150 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003151 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3152 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003153 }
3154 }
mgouda86543582025-10-29 20:58:16 +05303155 case flows.GROUP:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003156 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
mgouda86543582025-10-29 20:58:16 +05303157 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00003158 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 }
3160 }
3161 return nil
3162}
3163
Neha Sharma96b7bf22020-06-15 10:37:32 +00003164func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003165 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003166 fieldtype := ofbField.GetType()
mgouda86543582025-10-29 20:58:16 +05303167 switch fieldtype {
3168 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Esin Karamanccb714b2019-11-29 15:02:06 +00003169 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3170 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003172 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003173 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003174 }
mgouda86543582025-10-29 20:58:16 +05303175 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
Gamze Abakac43a66e2020-05-11 11:00:42 +00003176 pcp := ofbField.GetVlanPcp()
3177 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003178 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303179 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003180 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003181 }
3182 }
3183}
3184
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003186 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003187 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003188 } else {
3189 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003190 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003191 }
3192}
3193
Neha Sharma96b7bf22020-06-15 10:37:32 +00003194func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003195 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003196 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003197 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003198 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003199 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003200 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003201 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303202 log.Fields{
3203 "newinport": classifierInfo[InPort].(uint32),
3204 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003205 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303206 return olterrors.NewErrNotFound("child-in-port",
3207 log.Fields{
3208 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3209 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210 }
3211 }
3212 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003213 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003214 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003215 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003216 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003217 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003218 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303219 log.Fields{
3220 "newoutport": actionInfo[Output].(uint32),
3221 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003222 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303223 return olterrors.NewErrNotFound("out-port",
3224 log.Fields{
3225 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3226 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003227 }
3228 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003229 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003230 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003231 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003232 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303233 log.Fields{
3234 "newinport": actionInfo[Output].(uint32),
3235 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003236 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303237 return olterrors.NewErrNotFound("nni-port",
3238 log.Fields{
3239 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3240 "in-port": classifierInfo[InPort].(uint32),
3241 "out-port": actionInfo[Output].(uint32),
3242 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003243 }
3244 }
3245 }
3246 return nil
3247}
Gamze Abakafee36392019-10-03 11:17:24 +00003248
Neha Sharma96b7bf22020-06-15 10:37:32 +00003249func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003250 /* Metadata 8 bytes:
3251 Most Significant 2 Bytes = Inner VLAN
3252 Next 2 Bytes = Tech Profile ID(TPID)
3253 Least Significant 4 Bytes = Port ID
3254 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3255 subscriber related flows.
3256 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003257 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003258 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003259 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003260 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003261 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003262 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003263}
3264
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003265func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003266 for _, sliceElement := range slice {
3267 if sliceElement == item {
3268 return slice
3269 }
3270 }
3271 return append(slice, item)
3272}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303273
yasin saplie87d4bd2021-12-06 09:04:03 +00003274func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3275 for _, sliceElement := range slice {
3276 if sliceElement == item {
3277 return slice
3278 }
3279 }
3280 return append(slice, item)
3281}
3282
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303283// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003284func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003285 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
mgouda86543582025-10-29 20:58:16 +05303286 switch portType {
3287 case voltha.Port_PON_OLT:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003288 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003289 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003290 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003291 log.Fields{
3292 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003293 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003294 return uint32(0), err
3295 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003296 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303297 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303298 case voltha.Port_ETHERNET_NNI:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003299 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003300 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003301 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003302 log.Fields{
3303 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003304 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003305 return uint32(0), err
3306 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003307 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303308 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303309 case voltha.Port_ETHERNET_UNI:
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303310 if _, ok := action[Output]; ok {
3311 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
3312 if err != nil {
3313 logger.Debugw(ctx, "invalid-action-port-number",
3314 log.Fields{
3315 "port-number": action[Output].(uint32),
3316 "err": err})
3317 return uint32(0), nil
3318 }
3319 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
3320 return intfID, nil
3321 } else {
3322 logger.Debugw(ctx, "action-port-number-empty",
3323 log.Fields{
3324 "action": action})
3325 return uint32(0), nil
3326 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303327 }
3328 return uint32(0), nil
3329}
3330
3331// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003332func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3333 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3334 if err != nil {
3335 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3336 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3337 return
3338 }
3339 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003340
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003341 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003342 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003343 f.packetInGemPortLock.RUnlock()
3344
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303345 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003346 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003347 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 +05303348 log.Fields{
3349 "pktinkey": pktInkey,
3350 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003351 return
3352 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303353 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003354 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003355 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003356 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003357
npujarec5762e2020-01-01 14:08:48 +05303358 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003359 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 +05303360 log.Fields{
3361 "pktinkey": pktInkey,
3362 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303363}
3364
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003365// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003366func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
mgouda86543582025-10-29 20:58:16 +05303367 if len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003368 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003369 return 0, 0, errors.New("invalid packet length")
3370 }
3371 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3372 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3373
3374 var index int8
3375 if outerEthType == 0x8100 {
3376 if innerEthType == 0x8100 {
3377 // q-in-q 802.1ad or 802.1q double tagged packet.
3378 // get the inner vlanId
3379 index = 18
3380 } else {
3381 index = 14
3382 }
3383 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303384 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003385 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3386 return vlan, priority, nil
3387 }
3388 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3389 return 0, 0, nil
3390}
3391
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003392// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003393// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003394func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003395 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003396 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3397 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003398 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003399 "flow-id": flow.Id,
3400 "device-id": f.deviceHandler.device.Id})
3401 // Remove from device
3402 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3403 // DKB
3404 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3405 log.Fields{
3406 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003407 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003408 return err
3409 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003410
3411 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003412}
3413
khenaidoodc2116e2021-10-19 17:33:19 -04003414func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003415 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003416 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003417 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003418 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003419 }
3420
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003421 switch tpInst := tpInst.(type) {
3422 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003423 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003424 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003425 DeviceId: onuDeviceID,
3426 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003427 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003428 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003429 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003430 case *tp_pb.EponTechProfileInstance:
3431 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003432 DeviceId: onuDeviceID,
3433 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003435 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003436 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003437 default:
3438 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003439 }
khenaidoodc2116e2021-10-19 17:33:19 -04003440 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003441 DeviceId: onuDeviceID,
3442 UniId: uniID,
3443 TpInstancePath: tpPath,
3444 TechTpInstance: nil,
3445 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003446}
3447
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003448// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3449func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003450 intfID := sq.intfID
3451 onuID := sq.onuID
3452 uniID := sq.uniID
3453 tpID := sq.tpID
3454
3455 var reverseDirection string
3456 if sq.direction == tp_pb.Direction_UPSTREAM {
3457 reverseDirection = "downstream"
3458 } else {
3459 reverseDirection = "upstream"
3460 }
3461
3462 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003463 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003464 return
3465 }
3466
3467 // revert-delete tech-profile instance and delete tech profile id for onu
3468 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})
3469 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3470 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003471 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003472
3473 // free gem/alloc
3474 switch techprofileInst := sq.tpInst.(type) {
3475 case *tp_pb.TechProfileInstance:
3476 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003477 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003478 }
yasin saplibddc2d72022-02-08 13:10:17 +00003479 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003480 }
3481}
3482
3483// revertSchduler is called when CreateQueues request fails
3484func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3485 // revert scheduler
3486 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})
bseenivaa1622112025-12-11 18:24:02 +05303487 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
3488 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003489 IntfId: sq.intfID, OnuId: sq.onuID,
3490 UniId: sq.uniID, PortNo: sq.uniPort,
3491 TrafficScheds: TrafficSched})
bseenivaa1622112025-12-11 18:24:02 +05303492 cancel()
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003493}
Girish Gowdra6071f382021-12-14 12:52:04 +05303494
3495// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3496func (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 +00003497 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303498 if err != nil {
3499 return olterrors.NewErrNotFound("meter",
3500 log.Fields{"intf-id": intfID,
3501 "onu-id": onuID,
3502 "uni-id": uniID,
3503 "device-id": f.deviceHandler.device.Id}, err)
3504 }
3505
3506 if meterInfo != nil {
3507 // If RefCnt become 0 clear the meter information from the DB.
3508 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003509 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303510 return err
3511 }
3512 } else if meterInfo.MeterID != meterID {
3513 logger.Errorw(ctx, "meter-mismatch-for-direction",
3514 log.Fields{"direction": direction,
3515 "kv-store-meter-id": meterInfo.MeterID,
3516 "meter-id-in-flow": meterID,
3517 "device-id": f.deviceHandler.device.Id})
3518 return olterrors.NewErrInvalidValue(log.Fields{
3519 "unsupported": "meter-id",
3520 "kv-store-meter-id": meterInfo.MeterID,
3521 "meter-id-in-flow": meterID,
3522 "device-id": f.deviceHandler.device.Id}, nil)
3523 }
3524 }
3525 return nil
3526}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003527
3528func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3529 /* After we successfully remove the scheduler configuration on the OLT device,
3530 * delete the meter id on the KV store.
3531 */
yasin saplibddc2d72022-02-08 13:10:17 +00003532 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003533 if err != nil {
3534 return olterrors.NewErrAdapter("unable-to-remove-meter",
3535 log.Fields{
3536 "onu": sq.onuID,
3537 "device-id": f.deviceHandler.device.Id,
3538 "intf-id": sq.intfID,
3539 "onu-id": sq.onuID,
3540 "uni-id": sq.uniID,
3541 "uni-port": sq.uniPort}, err)
3542 }
3543 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3544 log.Fields{
3545 "dir": direction,
3546 "device-id": f.deviceHandler.device.Id,
3547 "intf-id": sq.intfID,
3548 "onu-id": sq.onuID,
3549 "uni-id": sq.uniID,
3550 "uni-port": sq.uniPort})
3551 return err
3552}