blob: 134b095f7b2bd541562e3ecf1212708ce1c70454 [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)
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530264 logger.Debugw(ctx, "initialization-of-flow-manager-success", log.Fields{"device-id": dh.device.Id})
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})
balaji.nagarajan29be8bc2026-01-26 16:31:41 +0530418 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, meterInfo, 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()
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530566 logger.Debugw(ctx, "successfully-created-traffic-schedulers", log.Fields{
Gamze Abakacb0e6772021-06-10 08:32:12 +0000567 "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 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530663 logger.Debugw(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Girish Gowdraf3728b12022-02-02 21:46:51 -0800664
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 {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530793 logger.Debugw(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
Girish Gowdra197acc12021-08-16 10:59:45 -0700794 "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 {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530820 logger.Debugw(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
Girish Gowdra197acc12021-08-16 10:59:45 -0700821 "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 {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530852 logger.Debugw(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})
balaji.nagarajan29be8bc2026-01-26 16:31:41 +0530985 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPortIDs); err != nil {
986 logger.Errorw(ctx, "error-while-uploading-onugeminfos-to-kv-store", log.Fields{"device-id": f.deviceHandler.device.Id, "onuID": onuID, "gemPort": gemPortIDs})
manikkaraj k9eb6cac2019-05-09 12:32:03 -0400987 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530988}
989
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700990func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530991 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000992 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700993 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
994 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530995 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700996 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
997 if err != nil || f.techprofile == nil {
998 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
999 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
1000 }
1001 logger.Debugw(ctx, "init-tech-profile-done",
1002 log.Fields{
1003 "intf-id": intfID,
1004 "device-id": f.deviceHandler.device.Id})
1005 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -07001006 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301007 }
1008 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001009 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
1010 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 +05301011}
1012
Gamze Abaka7650be62021-02-26 10:50:36 +00001013func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001014 flowContext.classifier[PacketTagType] = SingleTag
1015 // extract the cvid/inner-vid from the write metadata
1016 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1017 if writeMetadata != 0 {
1018 // Writemetadata field is 8 bytes
1019 // cvid is on the outer most two bytes of the write metadata
1020 cvid := (writeMetadata & 0xffff000000000000) >> 48
1021 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
1022 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
1023 flowContext.classifier[PacketTagType] = DoubleTag
1024 }
1025 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001026 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301027 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001028 "uplinkClassifier": flowContext.classifier,
1029 "uplinkAction": flowContext.action})
1030 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301031}
1032
Gamze Abaka7650be62021-02-26 10:50:36 +00001033func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1034 downlinkClassifier := flowContext.classifier
1035 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001036 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1037 downlinkClassifier[PacketTagType] = SingleTag
1038 // extract the cvid/inner-vid from the write metadata
1039 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1040 if writeMetadata != 0 {
1041 // Writemetadata field is 8 bytes
1042 // cvid is on the outer most two bytes of the write metadata
1043 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1044 downlinkClassifier[PacketTagType] = DoubleTag
1045 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301046 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001047 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301048 log.Fields{
1049 "downlinkClassifier": downlinkClassifier,
1050 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001051
Girish Gowdraffa52e52022-02-16 15:48:10 -08001052 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1053 // The matched vlan is the one that is getting popped.
1054 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1055 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1056 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1057 if ok {
1058 downlinkAction[VlanVid] = dlClVid & 0xfff
1059 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301060 }
1061
Gamze Abaka7650be62021-02-26 10:50:36 +00001062 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301063}
1064
Gamze Abaka7650be62021-02-26 10:50:36 +00001065func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001066 intfID := flowContext.intfID
1067 onuID := flowContext.onuID
1068 uniID := flowContext.uniID
1069 classifier := flowContext.classifier
1070 action := flowContext.action
1071 allocID := flowContext.allocID
1072 gemPortID := flowContext.gemPortID
1073 tpID := flowContext.tpID
1074 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001075 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301076 log.Fields{
1077 "intf-id": intfID,
1078 "onu-id": onuID,
1079 "uni-id": uniID,
1080 "device-id": f.deviceHandler.device.Id,
1081 "classifier": classifier,
1082 "action": action,
1083 "direction": direction,
1084 "alloc-id": allocID,
1085 "gemport-id": gemPortID,
1086 "logicalflow": *logicalFlow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001087
yasin saplibddc2d72022-02-08 13:10:17 +00001088 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001089 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001090 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301091 log.Fields{
1092 "device-id": f.deviceHandler.device.Id,
1093 "intf-id": intfID,
1094 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001095 return nil
yasin saplid0566272021-12-21 09:10:30 +00001096 } else if err != nil {
1097 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1098 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1099 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301100 }
yasin saplid0566272021-12-21 09:10:30 +00001101
David K. Bainbridge794735f2020-02-11 21:01:37 -08001102 classifierProto, err := makeOpenOltClassifierField(classifier)
1103 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301104 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301105 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001106 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301107 log.Fields{
1108 "classifier": *classifierProto,
1109 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001110 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001111 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301112 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301113 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001114 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301115 log.Fields{
1116 "action": *actionProto,
1117 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001118 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301119 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301120 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001121 log.Fields{
1122 "classifier": classifier,
1123 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301124 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001125 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301126 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001127
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001128 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001129 OnuId: int32(onuID),
1130 UniId: int32(uniID),
1131 FlowId: logicalFlow.Id,
1132 FlowType: direction,
1133 AllocId: int32(allocID),
1134 NetworkIntfId: int32(networkIntfID),
1135 GemportId: int32(gemPortID),
1136 Classifier: classifierProto,
1137 Action: actionProto,
1138 Priority: int32(logicalFlow.Priority),
1139 Cookie: logicalFlow.Cookie,
1140 PortNo: flowContext.portNo,
1141 TechProfileId: tpID,
1142 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1143 PbitToGemport: flowContext.pbitToGem,
1144 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001145 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001146 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001147 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301148 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001149 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301150 log.Fields{"direction": direction,
1151 "device-id": f.deviceHandler.device.Id,
1152 "flow": flow,
1153 "intf-id": intfID,
1154 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001155
David K. Bainbridge794735f2020-02-11 21:01:37 -08001156 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301157}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001158
Gamze Abaka7650be62021-02-26 10:50:36 +00001159func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001160 intfID := flowContext.intfID
1161 onuID := flowContext.onuID
1162 uniID := flowContext.uniID
1163 logicalFlow := flowContext.logicalFlow
1164 classifier := flowContext.classifier
1165 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301166
Neha Sharma96b7bf22020-06-15 10:37:32 +00001167 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301168 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301169 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001170 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301171 "action": action,
1172 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301174 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301175
1176 // Clear the action map
1177 for k := range action {
1178 delete(action, k)
1179 }
1180
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001181 action[TrapToHost] = true
1182 classifier[UDPSrc] = uint32(68)
1183 classifier[UDPDst] = uint32(67)
1184 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301185
yasin saplibddc2d72022-02-08 13:10:17 +00001186 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001187 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001188 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301189 log.Fields{
1190 "device-id": f.deviceHandler.device.Id,
1191 "intf-id": intfID,
1192 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001193 return nil
yasin saplid0566272021-12-21 09:10:30 +00001194 } else if err != nil {
1195 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1196 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1197 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301198 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301199
Neha Sharma96b7bf22020-06-15 10:37:32 +00001200 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301201 log.Fields{
1202 "ul_classifier": classifier,
1203 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001204 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301205 "intf-id": intfID,
1206 "onu-id": onuID,
1207 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301208
David K. Bainbridge794735f2020-02-11 21:01:37 -08001209 classifierProto, err := makeOpenOltClassifierField(classifier)
1210 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301211 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301212 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001213 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00001214 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001215 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301216 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301217 }
1218
David K. Bainbridge794735f2020-02-11 21:01:37 -08001219 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001220 OnuId: int32(onuID),
1221 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001222 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001223 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001224 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001225 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001226 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301227 Classifier: classifierProto,
1228 Action: actionProto,
1229 Priority: int32(logicalFlow.Priority),
1230 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001231 PortNo: flowContext.portNo,
1232 TechProfileId: flowContext.tpID,
1233 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1234 PbitToGemport: flowContext.pbitToGem,
1235 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001236 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001237 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001238 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow": dhcpFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001239 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001240 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301241 log.Fields{
1242 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001243 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301244 "intf-id": intfID,
1245 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301246
David K. Bainbridge794735f2020-02-11 21:01:37 -08001247 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301248}
1249
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001250// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001251func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1252 delete(flowContext.classifier, VlanVid)
1253 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001254}
1255
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001256// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001257func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001258 intfID := flowContext.intfID
1259 onuID := flowContext.onuID
1260 uniID := flowContext.uniID
1261 logicalFlow := flowContext.logicalFlow
1262 classifier := flowContext.classifier
1263 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001264
Neha Sharma96b7bf22020-06-15 10:37:32 +00001265 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001266 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301267 return olterrors.NewErrNotFound("nni-interface-id",
1268 log.Fields{
1269 "classifier": classifier,
1270 "action": action,
1271 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001272 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001273 }
1274
1275 // Clear the action map
1276 for k := range action {
1277 delete(action, k)
1278 }
1279
1280 action[TrapToHost] = true
1281 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001282
yasin saplibddc2d72022-02-08 13:10:17 +00001283 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001284 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001285 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001286 return nil
yasin saplid0566272021-12-21 09:10:30 +00001287 } else if err != nil {
1288 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1289 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1290 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001291 }
1292
Neha Sharma96b7bf22020-06-15 10:37:32 +00001293 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301294 log.Fields{
1295 "ul_classifier": classifier,
1296 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001297 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301298 "device-id": f.deviceHandler.device.Id,
1299 "intf-id": intfID,
1300 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001301
David K. Bainbridge794735f2020-02-11 21:01:37 -08001302 classifierProto, err := makeOpenOltClassifierField(classifier)
1303 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301304 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001305 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001306 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301307 log.Fields{
1308 "classifier": *classifierProto,
1309 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001310 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001311 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301312 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001313 }
1314
David K. Bainbridge794735f2020-02-11 21:01:37 -08001315 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001316 OnuId: int32(onuID),
1317 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001318 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001319 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001320 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001321 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001322 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001323 Classifier: classifierProto,
1324 Action: actionProto,
1325 Priority: int32(logicalFlow.Priority),
1326 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001327 PortNo: flowContext.portNo,
1328 TechProfileId: flowContext.tpID,
1329 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1330 PbitToGemport: flowContext.pbitToGem,
1331 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001332 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001333
David K. Bainbridge794735f2020-02-11 21:01:37 -08001334 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001335 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 -08001336 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001337
David K. Bainbridge794735f2020-02-11 21:01:37 -08001338 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001339}
1340
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001341// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001342func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1343 intfID := flowContext.intfID
1344 onuID := flowContext.onuID
1345 uniID := flowContext.uniID
1346 portNo := flowContext.portNo
1347 allocID := flowContext.allocID
1348 gemPortID := flowContext.gemPortID
1349 logicalFlow := flowContext.logicalFlow
1350 classifier := flowContext.classifier
1351 action := flowContext.action
1352
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001353 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301354 log.Fields{
1355 "intf-id": intfID,
1356 "onu-id": onuID,
1357 "port-no": portNo,
1358 "alloc-id": allocID,
1359 "gemport-id": gemPortID,
1360 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001361 "flow": logicalFlow,
1362 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301363
1364 uplinkClassifier := make(map[string]interface{})
1365 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301366
manikkaraj kbf256be2019-03-25 00:13:48 +05301367 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001368 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001369 uplinkClassifier[PacketTagType] = SingleTag
1370 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001371 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301372 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001373 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001374 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001375 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001376 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301377 "device-id": f.deviceHandler.device.Id,
1378 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001379 "intf-id": intfID,
1380 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001381 return nil
yasin saplid0566272021-12-21 09:10:30 +00001382 } else if err != nil {
1383 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1384 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1385 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301386 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301387 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001388 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301389 log.Fields{
1390 "ul_classifier": uplinkClassifier,
1391 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001392 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301393 "device-id": f.deviceHandler.device.Id,
1394 "intf-id": intfID,
1395 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301396
David K. Bainbridge794735f2020-02-11 21:01:37 -08001397 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1398 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301399 return olterrors.NewErrInvalidValue(log.Fields{
1400 "classifier": uplinkClassifier,
1401 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301402 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001403 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301404 log.Fields{
1405 "classifier": *classifierProto,
1406 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001407 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001408 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301409 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301410 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001411 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301412 log.Fields{
1413 "action": *actionProto,
1414 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001415 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301416 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301417 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001418 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301419 "action": action,
1420 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301422 }
1423
David K. Bainbridge794735f2020-02-11 21:01:37 -08001424 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001425 OnuId: int32(onuID),
1426 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001427 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001428 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001429 AllocId: int32(allocID),
1430 NetworkIntfId: int32(networkIntfID),
1431 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301432 Classifier: classifierProto,
1433 Action: actionProto,
1434 Priority: int32(logicalFlow.Priority),
1435 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001436 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001437 TechProfileId: flowContext.tpID,
1438 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1439 PbitToGemport: flowContext.pbitToGem,
1440 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001441 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001442 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001443 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": upstreamFlow}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001444 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001445 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301446 log.Fields{
1447 "device-id": f.deviceHandler.device.Id,
1448 "onu-id": onuID,
1449 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001450 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301451 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001452
David K. Bainbridge794735f2020-02-11 21:01:37 -08001453 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301454}
1455
David K. Bainbridge794735f2020-02-11 21:01:37 -08001456func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001457 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001458
1459 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1460 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1461 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001462 if vlanID != ReservedVlan {
1463 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001464 classifier.OVid = vid
1465 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301466 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001467 // The classifierInfo[Metadata] is set for the following flows
1468 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1469 // - Mcast flow that points to a group in the treatment
1470 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1471 // - inner vid for a double tagged packet in the datapath flow
1472 // - outer vid for a single tagged packet in the datapath flow
1473 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001474 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1475 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301476 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1477 // 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 +05301478 // 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 +05301479 // becomes the IVid.
1480 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1481 if vid != ReservedVlan {
1482 classifier.IVid = vid
1483 }
1484 } else {
1485 if vid != ReservedVlan {
1486 classifier.OVid = vid
1487 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001488 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301489 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301490 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001491 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301492 classifier.OPbits = vlanPcp
1493 } else {
1494 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301495 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001496 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1497 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1498 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1499 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001500 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001501 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001502 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1503 classifier.PktTagType = pktTagType
1504
1505 switch pktTagType {
1506 case SingleTag:
1507 case DoubleTag:
1508 case Untagged:
1509 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001510 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301511 }
1512 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001513 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301514}
1515
Akash Kankanala041a2122024-10-16 15:49:22 +05301516// nolint: unparam
1517// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001518func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001519 var actionCmd openoltpb2.ActionCmd
1520 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301521 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001522 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001523 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301524 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001525 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001526 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001527 action.Cmd.RemarkInnerPbits = true
1528 action.IPbits = actionInfo[VlanPcp].(uint32)
1529 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001530 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001531 action.Cmd.TranslateInnerTag = true
1532 action.IVid = actionInfo[VlanVid].(uint32)
1533 }
1534 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001535 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001536 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001537 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301538 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001539 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001540 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001541 action.OPbits = actionInfo[VlanPcp].(uint32)
1542 action.Cmd.RemarkOuterPbits = true
1543 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001544 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001545 action.IVid = classifierInfo[VlanVid].(uint32)
1546 action.Cmd.TranslateInnerTag = true
1547 }
1548 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001549 } else if _, ok := actionInfo[TrapToHost]; ok {
1550 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001551 } else if _, ok := actionInfo[VlanVid]; ok {
1552 // Translate outer vid
1553 action.Cmd.TranslateOuterTag = true
1554 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301555 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301556 // When OLT is transparent to vlans no-action is valid.
1557 /*
1558 else {
1559 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1560 }
1561 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001562 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301563}
1564
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001565// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001566func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001567 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301568}
1569
Gamze Abakafee36392019-10-03 11:17:24 +00001570// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001571// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1572// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1573// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1574// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1575// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1576// because it was observed that if the ONU device was deleted too soon after the flows were
1577// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1578// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1579// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001580func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001581 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001582 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1583
Gamze Abakafee36392019-10-03 11:17:24 +00001584 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001585 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001586 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001587 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001588 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001589 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1590 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1591 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1592 log.Fields{
1593 "tp-id": tpID,
1594 "path": tpPath})
1595 }
1596 switch tpInstance := tpInst.(type) {
1597 case *tp_pb.TechProfileInstance:
1598 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1599 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1600 }
1601 // Force cleanup scheduler/queues -- end
1602
1603 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301604 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001605 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301606 // return err
1607 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001608 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001609 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 +00001610 }
1611 return nil
1612}
1613
1614// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301615func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001616 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001617 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001618 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001619 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301620 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1621 log.Fields{
1622 "tp-id": tpID,
1623 "uni-port-name": uniPortName,
1624 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001625 }
1626 return nil
1627}
1628
David K. Bainbridge794735f2020-02-11 21:01:37 -08001629func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001630 var intfID uint32
1631 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1632 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1633 */
1634 if deviceFlow.AccessIntfId != -1 {
1635 intfID = uint32(deviceFlow.AccessIntfId)
1636 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001637 // We need to log the valid interface ID.
1638 // 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 +00001639 intfID = uint32(deviceFlow.NetworkIntfId)
1640 }
1641
Neha Sharma96b7bf22020-06-15 10:37:32 +00001642 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301643 "flow": *deviceFlow,
1644 "device-id": f.deviceHandler.device.Id,
1645 "intf-id": intfID})
bseenivaa1622112025-12-11 18:24:02 +05301646 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1647 _, err := f.deviceHandler.Client.FlowAdd(subCtx, deviceFlow)
1648 cancel()
Daniele Rossi22db98e2019-07-11 11:50:00 +00001649
1650 st, _ := status.FromError(err)
1651 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001652 logger.Debug(ctx, "flow-already-exists", log.Fields{
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001653 "err": err,
1654 "deviceFlow": deviceFlow,
Shrey Baid26912972020-04-16 21:02:31 +05301655 "device-id": f.deviceHandler.device.Id,
1656 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001657 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301658 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001659
1660 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001661 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301662 log.Fields{"err": err,
1663 "device-flow": deviceFlow,
1664 "device-id": f.deviceHandler.device.Id,
1665 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001666 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001667 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001668 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301669 log.Fields{
1670 "flow": *deviceFlow,
1671 "device-id": f.deviceHandler.device.Id,
1672 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001673
yasin saplid0566272021-12-21 09:10:30 +00001674 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1675 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1676 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001677 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001678 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001679}
1680
Neha Sharma96b7bf22020-06-15 10:37:32 +00001681func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1682 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301683 log.Fields{
1684 "flow": *deviceFlow,
1685 "device-id": f.deviceHandler.device.Id})
bseenivaa1622112025-12-11 18:24:02 +05301686 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1687 _, err := f.deviceHandler.Client.FlowRemove(subCtx, deviceFlow)
1688 cancel()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001689 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001690 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001691 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301692 log.Fields{
1693 "err": err,
1694 "deviceFlow": deviceFlow,
1695 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301696 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001697 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001698 }
Girish Kumarf26e4882020-03-05 06:49:10 +00001699 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001700 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001701 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001702 "of-flow-id": ofFlowID,
1703 "flow": *deviceFlow,
1704 "device-id": f.deviceHandler.device.Id,
1705 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001706 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301707}
1708
David K. Bainbridge794735f2020-02-11 21:01:37 -08001709func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001710 classifierInfo := make(map[string]interface{})
1711 actionInfo := make(map[string]interface{})
1712
1713 classifierInfo[EthType] = uint32(LldpEthType)
1714 classifierInfo[PacketTagType] = Untagged
1715 actionInfo[TrapToHost] = true
1716
1717 // LLDP flow is installed to trap LLDP packets on the NNI port.
1718 // We manage flow_id resource pool on per PON port basis.
1719 // Since this situation is tricky, as a hack, we pass the NNI port
1720 // index (network_intf_id) as PON port Index for the flow_id resource
1721 // pool. Also, there is no ONU Id available for trapping LLDP packets
1722 // on NNI port, use onu_id as -1 (invalid)
1723 // ****************** CAVEAT *******************
1724 // This logic works if the NNI Port Id falls within the same valid
1725 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1726 // we need to have a re-look at this.
1727 // *********************************************
1728
1729 var onuID = -1
1730 var uniID = -1
1731 var gemPortID = -1
1732
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001733 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001734 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301735 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001736 }
yasin saplibddc2d72022-02-08 13:10:17 +00001737 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001738 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001739 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001740 return nil
yasin saplid0566272021-12-21 09:10:30 +00001741 } else if err != nil {
1742 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1743 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1744 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001745 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001746
David K. Bainbridge794735f2020-02-11 21:01:37 -08001747 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1748 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301749 return olterrors.NewErrInvalidValue(
1750 log.Fields{
1751 "classifier": classifierInfo,
1752 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001753 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301755 log.Fields{
1756 "classifier": *classifierProto,
1757 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001758 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001759 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301760 return olterrors.NewErrInvalidValue(
1761 log.Fields{
1762 "action": actionInfo,
1763 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001764 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001765 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301766 log.Fields{
1767 "action": *actionProto,
1768 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001769
1770 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1771 OnuId: int32(onuID), // OnuId not required
1772 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001773 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001774 FlowType: Downstream,
1775 NetworkIntfId: int32(networkInterfaceID),
1776 GemportId: int32(gemPortID),
1777 Classifier: classifierProto,
1778 Action: actionProto,
1779 Priority: int32(flow.Priority),
1780 Cookie: flow.Cookie,
1781 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001782 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001783 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301784 log.Fields{
1785 "flow": downstreamflow,
1786 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001787 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001788 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301789 log.Fields{
1790 "device-id": f.deviceHandler.device.Id,
1791 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001792 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001793
David K. Bainbridge794735f2020-02-11 21:01:37 -08001794 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301795}
1796
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001797func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1798 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001799}
1800
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001801// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001802func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001803 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1804 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1805 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001806 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301807 log.Fields{
1808 "intf-id": intfID,
1809 "onu-id": onuID,
1810 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001811 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001812 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301813 return nil, olterrors.NewErrNotFound("onu-child-device",
1814 log.Fields{
1815 "onu-id": onuID,
1816 "intf-id": intfID,
1817 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001818 }
khenaidoo106c61a2021-08-11 18:05:46 -04001819 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 +05301820 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001821 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1822 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001823 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301824 log.Fields{
1825 "intf-id": intfID,
1826 "onu-id": onuID,
1827 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001828 }
1829
1830 return onuDev.(*OnuDevice), nil
1831}
1832
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001833// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001834func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1835 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301836 log.Fields{
1837 "pon-port": intfID,
1838 "onu-id": onuID,
1839 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001840 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001841 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001842 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301843 return nil, olterrors.NewErrNotFound("onu",
1844 log.Fields{
1845 "interface-id": parentPortNo,
1846 "onu-id": onuID,
1847 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001848 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301849 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001850 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
1852 "device-id": f.deviceHandler.device.Id,
1853 "child_device_id": onuDevice.Id,
1854 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301855 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301856}
1857
Neha Sharma96b7bf22020-06-15 10:37:32 +00001858func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1859 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301860 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001861 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301862 log.Fields{
1863 "intf-id": intfID,
1864 "onu-id": onuID,
1865 "uni-id": uniID,
1866 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001867 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301868 }
1869
khenaidoodc2116e2021-10-19 17:33:19 -04001870 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001871 DeviceId: onuDev.deviceID,
1872 UniId: uniID,
1873 TpInstancePath: tpPath,
1874 GemPortId: gemPortID,
1875 }
1876 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": *delGemPortMsg, "child-device-id": onuDev.deviceID})
1877
1878 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301879 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1880 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001881 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1882 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301883 "onu-id": onuDev.deviceID,
1884 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001885 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301886 }
khenaidoo106c61a2021-08-11 18:05:46 -04001887
Neha Sharma96b7bf22020-06-15 10:37:32 +00001888 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301889 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001890 "msg": delGemPortMsg,
1891 "from-adapter": f.deviceHandler.device.Type,
1892 "to-adapter": onuDev.deviceType,
1893 "device-id": f.deviceHandler.device.Id,
1894 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301895 return nil
1896}
1897
Neha Sharma96b7bf22020-06-15 10:37:32 +00001898func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1899 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301900 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001901 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301902 log.Fields{
1903 "intf-id": intfID,
1904 "onu-id": onuID,
1905 "uni-id": uniID,
1906 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001907 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301908 }
1909
khenaidoodc2116e2021-10-19 17:33:19 -04001910 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001911 DeviceId: onuDev.deviceID,
1912 UniId: uniID,
1913 TpInstancePath: tpPath,
1914 AllocId: allocID,
1915 }
1916
Neha Sharma96b7bf22020-06-15 10:37:32 +00001917 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301918 log.Fields{
1919 "msg": *delTcontMsg,
1920 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001921
1922 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301923 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1924 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001925 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1926 "to-adapter": onuDev.adapterEndpoint,
1927 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301928 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001929 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301930 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001931 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301932 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001933 "msg": delTcontMsg,
1934 "device-id": f.deviceHandler.device.Id,
1935 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301936 return nil
1937}
1938
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001939// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001940// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001941func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05301942 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool, nniIntfID uint32) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001943 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001944
Girish Gowdraa482f272021-03-24 23:04:19 -07001945 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001946 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001947 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1948 log.Fields{
1949 "tpPath": tpPath,
1950 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001951
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001952 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001953 if err != nil || techprofileInst == nil {
1954 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1955 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1956 if childDevice == nil {
1957 // happens when subscriber un-provision is immediately followed by child device delete
1958 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1959 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1960 return nil
1961 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001962 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1963 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001964 log.Fields{
1965 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001966 "path": tpPath}, err).Log()
1967 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001968 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001969
1970 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001971 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001972 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001973 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1974 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001975 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1976 if err != nil {
1977 return err
1978 }
1979 used := false
1980 for _, id := range flowIDs {
1981 if flowID != id {
1982 used = true
1983 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001984 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07001985 }
1986 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001987 for i, flowIDinMap := range flowIDs {
1988 if flowIDinMap == flowID {
1989 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00001990 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001991 return err
1992 }
1993 break
1994 }
1995 }
1996 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
1997 log.Fields{
1998 "gemport-id": gemPortID,
1999 "usedByFlows": flowIDs,
2000 "currentFlow": flowID,
2001 "device-id": f.deviceHandler.device.Id})
2002 allGemPortsFree = false
2003 }
2004 }
2005 if !allGemPortsFree {
2006 return nil
2007 }
2008 }
2009
2010 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 -08002011
2012 // 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 +00002013 switch techprofileInst := techprofileInst.(type) {
2014 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08002015 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2016 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00002017 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08002018
yasin saplibddc2d72022-02-08 13:10:17 +00002019 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002020 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2021 log.Fields{
2022 "err": err,
2023 "intf": intfID,
2024 "onu-id": onuID,
2025 "uni-id": uniID,
2026 "device-id": f.deviceHandler.device.Id,
2027 "gemport-id": gemPortID})
2028 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002029 }
2030 // Remove queues at OLT in upstream and downstream direction
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302031 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 +05302032 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002033 logger.Warn(ctx, err)
2034 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302035 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2036 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002037 logger.Warn(ctx, err)
2038 }
2039 }
2040
2041 switch techprofileInst := techprofileInst.(type) {
2042 case *tp_pb.TechProfileInstance:
2043 // 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 +05302044 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2045 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002046 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002047 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002048 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302049 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002050 logger.Warn(ctx, err)
2051 }
2052 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002053 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002054 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002055 } else {
2056 // just remove meter reference for the upstream direction for the current pon/onu/uni
2057 // 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 +05302058 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002059 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002060 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002061 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2062 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002063 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002064 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002065
Girish Gowdraf3728b12022-02-02 21:46:51 -08002066 // 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 +05302067 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002068 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302069 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002070 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002071 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002072 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002073 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002074 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002075 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002076 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302077 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002078 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302079 "onu-id": onuID,
2080 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002081 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002082 "alloc-id": techprofileInst.AllocId,
2083 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002084 }
yasin saplibddc2d72022-02-08 13:10:17 +00002085 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302086 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2087 logger.Warn(ctx, err)
2088 }
2089 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2090 logger.Warn(ctx, err)
2091 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002092 default:
2093 logger.Errorw(ctx, "error-unknown-tech",
2094 log.Fields{
2095 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002096 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002097
2098 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2099 switch techprofileInst := techprofileInst.(type) {
2100 case *tp_pb.TechProfileInstance:
2101 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2102 // Delete the gem port on the ONU.
2103 if sendDeleteGemRequest {
2104 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2105 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2106 log.Fields{
2107 "err": err,
2108 "intfID": intfID,
2109 "onu-id": onuID,
2110 "uni-id": uniID,
2111 "device-id": f.deviceHandler.device.Id,
2112 "gemport-id": gemPort.GemportId})
2113 }
yasin saplibddc2d72022-02-08 13:10:17 +00002114 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002115 }
2116 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302117 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302118 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2119 logger.Warn(ctx, err)
2120 }
2121 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2122 logger.Warn(ctx, err)
2123 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002124 }
2125
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302126 return nil
2127}
2128
David K. Bainbridge794735f2020-02-11 21:01:37 -08002129// nolint: gocyclo
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302130func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string, nni_port uint32) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302131 logger.Debugw(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302132 log.Fields{
2133 "flowDirection": flowDirection,
2134 "flow": *flow,
2135 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002136
2137 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002138 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002139 }
2140
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302141 var ethType, ipProto, inPort uint32
2142 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05302143 switch field.Type {
2144 case flows.IP_PROTO:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302145 ipProto = field.GetIpProto()
2146 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
mgouda86543582025-10-29 20:58:16 +05302147 case flows.ETH_TYPE:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302148 ethType = field.GetEthType()
2149 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
mgouda86543582025-10-29 20:58:16 +05302150 case flows.IN_PORT:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302151 inPort = field.GetPort()
2152 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2153 }
2154 }
2155 portType := plt.IntfIDToPortTypeName(inPort)
2156 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2157 (portType == voltha.Port_ETHERNET_NNI) {
2158 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2159 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2160 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2161 // No more processing needed for trap from nni flows.
2162 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302163
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302164 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302165 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002166 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002167 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302168 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002169 onuID := int32(onu)
2170 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002171 tpID, err := getTpIDFromFlow(ctx, flow)
2172 if err != nil {
2173 return olterrors.NewErrNotFound("tp-id",
2174 log.Fields{
2175 "flow": flow,
2176 "intf-id": Intf,
2177 "onu-id": onuID,
2178 "uni-id": uniID,
2179 "device-id": f.deviceHandler.device.Id}, err)
2180 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302181
Neha Sharma96b7bf22020-06-15 10:37:32 +00002182 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302183 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002184 "flow-id": flow.Id,
2185 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302186 "onu-id": onuID,
2187 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302188
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002189 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2190 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002191 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2192 return err
2193 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002194
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302195 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true, nni_port); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002196 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2197 "flow-id": flow.Id,
2198 "device-id": f.deviceHandler.device.Id,
2199 "onu-id": onuID,
2200 "intf": Intf,
2201 "err": err,
2202 })
2203 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302204 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002205
Girish Gowdra82c80982021-03-26 16:22:02 -07002206 // Decrement reference count for the meter associated with the given <(pon_id, onu_id, uni_id)>/<tp_id>/meter_id/<direction>
balaji.nagarajan29be8bc2026-01-26 16:31:41 +05302207 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, nil, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002208 return err
2209 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002210 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002211}
2212
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002213// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002214func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302215 logger.Debugw(ctx, "removing-flow", log.Fields{"flow": *flow})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302216 var direction string
2217 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002218
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302219 for _, action := range flows.GetActions(flow) {
2220 if action.Type == flows.OUTPUT {
2221 if out := action.GetOutput(); out != nil {
2222 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002223 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302224 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002225 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002226 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002227 }
2228 }
2229 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002230
2231 if flows.HasGroup(flow) {
2232 direction = Multicast
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002233 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302234 direction = Upstream
2235 } else {
2236 direction = Downstream
2237 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302238
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302239 var nni_port uint32
2240 if direction == Upstream {
2241 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2242 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2243 }
2244 } else {
2245 classifierInfo := make(map[string]interface{})
2246 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
2247 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2248 }
2249
Girish Gowdracefae192020-03-19 18:14:10 -07002250 // Serialize flow removes on a per subscriber basis
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302251 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction, nni_port)
Girish Gowdracefae192020-03-19 18:14:10 -07002252
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002253 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002254}
2255
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002256// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002257func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002258 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002259 if ethType, ok := classifierInfo[EthType]; ok {
2260 if ethType.(uint32) == IPv4EthType {
2261 if ipProto, ok := classifierInfo[IPProto]; ok {
2262 if ipProto.(uint32) == IgmpProto {
2263 return true
2264 }
2265 }
2266 }
2267 }
2268 }
2269 return false
2270}
2271
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002272// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002273func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002274 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2275 // The device itself is going to be reset as part of deletion. So nothing to be done.
2276 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2277 return nil
2278 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002279 // Step1 : Fill flowControlBlock
2280 // Step2 : Push the flowControlBlock to ONU channel
2281 // Step3 : Wait on response channel for response
2282 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002283 startTime := time.Now()
2284 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002285 errChan := make(chan error)
2286 flowCb := flowControlBlock{
2287 ctx: ctx,
2288 addFlow: addFlow,
2289 flow: flow,
2290 flowMetadata: flowMetadata,
2291 errChan: &errChan,
2292 }
2293 inPort, outPort := getPorts(flow)
2294 var onuID uint32
2295 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002296 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002297 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002298 if f.flowHandlerRoutineActive[onuID] {
2299 // inPort or outPort is InvalidPort for trap-from-nni flows.
2300 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2301 // Send the flowCb on the ONU flow channel
2302 f.incomingFlows[onuID] <- flowCb
2303 // Wait on the channel for flow handlers return value
2304 err := <-errChan
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302305 logger.Debugw(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002306 return err
2307 }
2308 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2309 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002310}
2311
2312// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2313// 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 -07002314func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002315 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002316 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002317 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002318 // block on the channel to receive an incoming flow
2319 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002320 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002321 if flowCb.addFlow {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302322 logger.Debug(flowCb.ctx, "adding-flow-start")
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002323 startTime := time.Now()
2324 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302325 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds(), "flow": flowCb.flow})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002326 // Pass the return value over the return channel
2327 *flowCb.errChan <- err
2328 } else {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302329 logger.Debug(flowCb.ctx, "removing-flow-start")
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002330 startTime := time.Now()
2331 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302332 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds(), "flow": flowCb.flow})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002333 // Pass the return value over the return channel
2334 *flowCb.errChan <- err
2335 }
2336 case <-stopHandler:
2337 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2338 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002339 }
2340 }
2341}
2342
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002343// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002344func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002345 for i, v := range f.stopFlowHandlerRoutine {
2346 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002347 select {
2348 case v <- true:
2349 case <-time.After(time.Second * 5):
2350 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2351 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002352 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002353 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002354 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002355 f.stopFlowHandlerRoutine = nil
2356
2357 if f.incomingFlows != nil {
2358 for k := range f.incomingFlows {
2359 if f.incomingFlows[k] != nil {
2360 f.incomingFlows[k] = nil
2361 }
2362 }
2363 f.incomingFlows = nil
2364 }
2365
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002366 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002367 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2368}
2369
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002370// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302371// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002372func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002373 classifierInfo := make(map[string]interface{})
2374 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002375 var UsMeterID uint32
2376 var DsMeterID uint32
2377
Neha Sharma96b7bf22020-06-15 10:37:32 +00002378 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302379 log.Fields{
2380 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002381 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002382 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002383
Neha Sharma96b7bf22020-06-15 10:37:32 +00002384 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002385 if err != nil {
2386 // Error logging is already done in the called function
2387 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002388 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302389 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002390
Esin Karamanccb714b2019-11-29 15:02:06 +00002391 if flows.HasGroup(flow) {
2392 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002393 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002394 }
2395
manikkaraj k17652a72019-05-06 09:06:36 -04002396 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002397 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002398 if err != nil {
2399 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002400 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002401 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002402
Neha Sharma96b7bf22020-06-15 10:37:32 +00002403 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302404 log.Fields{
2405 "classifierinfo_inport": classifierInfo[InPort],
2406 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002407 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002408
Humera Kouser94d7a842019-08-25 19:04:32 -04002409 if ethType, ok := classifierInfo[EthType]; ok {
2410 if ethType.(uint32) == LldpEthType {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302411 logger.Debug(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002412 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002413 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002414 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002415 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002416 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2417 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2418 }
2419 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002420 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002421 if ipProto, ok := classifierInfo[IPProto]; ok {
2422 if ipProto.(uint32) == IPProtoDhcp {
2423 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302424 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002425 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002426 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002427 }
2428 }
2429 }
2430 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002431 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002432 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002433 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002434 }
A R Karthick1f85b802019-10-11 05:06:05 +00002435
yasin saplibddc2d72022-02-08 13:10:17 +00002436 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002437
Girish Gowdra6071f382021-12-14 12:52:04 +05302438 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002439 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302440 return olterrors.NewErrNotFound("tpid-for-flow",
2441 log.Fields{
2442 "flow": flow,
2443 "intf-id": IntfID,
2444 "onu-id": onuID,
2445 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002446 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002447 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302448 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302449 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302450 "intf-id": intfID,
2451 "onu-id": onuID,
2452 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002453 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002454 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002455 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302456 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2457 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2458 return err
2459 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002460 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002461 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302463 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2464 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2465 return err
2466 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002467 }
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302468
2469 var nni_port uint32
2470 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2471 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2472 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2473 }
2474 } else {
2475 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2476 }
2477
2478 return f.processAddFlow(ctx, intfID, nni_port, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002479}
Girish Gowdra3d633032019-12-10 16:37:05 +05302480
Esin Karamanccb714b2019-11-29 15:02:06 +00002481// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002482func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302483 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002484 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302485 "classifier-info": classifierInfo,
2486 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002487
Esin Karaman65409d82020-03-18 10:58:18 +00002488 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002489 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002490 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002491 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002492
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002493 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002494
David K. Bainbridge794735f2020-02-11 21:01:37 -08002495 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002496
yasin saplibddc2d72022-02-08 13:10:17 +00002497 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002498 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002499 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002500 return nil
yasin saplid0566272021-12-21 09:10:30 +00002501 } else if err != nil {
2502 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2503 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2504 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002505 }
yasin saplid0566272021-12-21 09:10:30 +00002506
David K. Bainbridge794735f2020-02-11 21:01:37 -08002507 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2508 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002509 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002510 }
2511 groupID := actionInfo[GroupID].(uint32)
2512 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002513 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002514 FlowType: Multicast,
2515 NetworkIntfId: int32(networkInterfaceID),
2516 GroupId: groupID,
2517 Classifier: classifierProto,
2518 Priority: int32(flow.Priority),
2519 Cookie: flow.Cookie}
2520
Kent Hagermane6ff1012020-07-14 15:07:53 -04002521 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002522 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow": multicastFlow}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002523 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002524 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302525 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002526 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302527 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002528 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002529 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002530 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302531 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002532 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002533 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002534 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002535 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002536
David K. Bainbridge794735f2020-02-11 21:01:37 -08002537 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002538}
2539
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002540// 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 +00002541func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2542 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002543 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002544 if err != nil {
2545 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2546 }
2547 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002548 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002549
2550 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2551 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002552}
2553
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002554// sendTPDownloadMsgToChild send payload
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002555func (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 +00002556 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302557 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002558 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302559 log.Fields{
2560 "intf-id": intfID,
2561 "onu-id": onuID,
2562 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002563 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302564 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002565 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002566
yasin saplibddc2d72022-02-08 13:10:17 +00002567 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002568 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002569 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002570 UniId: uniID,
2571 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04002572 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: &tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002573 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002574 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": *tpDownloadMsg})
khenaidoo106c61a2021-08-11 18:05:46 -04002575
2576 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2577 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302578 return olterrors.NewErrCommunication("send-techprofile-download-request",
2579 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002580 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302581 "to-adapter": onuDev.deviceType,
2582 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002583 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002584 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302585 logger.Debugw(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302586 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302587}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002588
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002589// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302590func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002591 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002592
mgouda86543582025-10-29 20:58:16 +05302593 switch packetIn.IntfType {
2594 case "pon":
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002595 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002596 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002597 onuID, uniID := packetIn.OnuId, packetIn.UniId
2598 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 +00002599
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002600 if packetIn.PortNo != 0 {
2601 logicalPortNum = packetIn.PortNo
2602 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002603 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002604 }
2605 // 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 +00002606 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
mgouda86543582025-10-29 20:58:16 +05302607 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002608 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002609 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002610
2611 if logger.V(log.DebugLevel) {
2612 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2613 log.Fields{
2614 "logical-port-num": logicalPortNum,
2615 "intf-type": packetIn.IntfType,
2616 "packet": hex.EncodeToString(packetIn.Pkt),
2617 })
2618 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 return logicalPortNum, nil
2620}
2621
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002622// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002623func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002624 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002625
2626 ctag, priority, err := getCTagFromPacket(ctx, packet)
2627 if err != nil {
2628 return 0, err
2629 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302630
Esin Karaman7fb80c22020-07-16 14:23:33 +00002631 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002632 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002633 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002634 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002635 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302636 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002637 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302638 log.Fields{
2639 "pktinkey": pktInkey,
2640 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002641
2642 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002643 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302644 // 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 +00002645 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302646 if err == nil {
2647 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002648 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302649 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002650 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002651 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302652 log.Fields{
2653 "pktinkey": pktInkey,
2654 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302655 return gemPortID, nil
2656 }
2657 }
Shrey Baid26912972020-04-16 21:02:31 +05302658 return uint32(0), olterrors.NewErrNotFound("gem-port",
2659 log.Fields{
2660 "pktinkey": pktInkey,
2661 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002662}
2663
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002664func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2665 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002666 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002667 classifier[PacketTagType] = DoubleTag
2668 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002669 /* We manage flowId resource pool on per PON port basis.
2670 Since this situation is tricky, as a hack, we pass the NNI port
2671 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002672 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002673 on NNI port, use onu_id as -1 (invalid)
2674 ****************** CAVEAT *******************
2675 This logic works if the NNI Port Id falls within the same valid
2676 range of PON Port Ids. If this doesn't work for some OLT Vendor
2677 we need to have a re-look at this.
2678 *********************************************
2679 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002680 onuID := -1
2681 uniID := -1
2682 gemPortID := -1
2683 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002684 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302685 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302686 return olterrors.NewErrNotFound("nni-intreface-id",
2687 log.Fields{
2688 "classifier": classifier,
2689 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002690 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302691 }
2692
yasin saplibddc2d72022-02-08 13:10:17 +00002693 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002694 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002695 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002696 return nil
yasin saplid0566272021-12-21 09:10:30 +00002697 } else if err != nil {
2698 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2699 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2700 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002701 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002702
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002703 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2704 log.Fields{
2705 "classifier": classifier,
2706 "action": action,
2707 "flowId": logicalFlow.Id,
2708 "intf-id": networkInterfaceID})
2709
David K. Bainbridge794735f2020-02-11 21:01:37 -08002710 classifierProto, err := makeOpenOltClassifierField(classifier)
2711 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002712 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002713 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002714 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002715 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002716 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002717 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002718 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002719 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": *actionProto})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002720 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2721 OnuId: int32(onuID), // OnuId not required
2722 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002723 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002724 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002725 AllocId: int32(allocID), // AllocId not used
2726 NetworkIntfId: int32(networkInterfaceID),
2727 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002728 Classifier: classifierProto,
2729 Action: actionProto,
2730 Priority: int32(logicalFlow.Priority),
2731 Cookie: logicalFlow.Cookie,
2732 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002733 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002734 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002735 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002736 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002737 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002738}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002739
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002740// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002741func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2742 var packetType string
2743 ovid, ivid := false, false
2744 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2745 vid := vlanID & VlanvIDMask
2746 if vid != ReservedVlan {
2747 ovid = true
2748 }
2749 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002750
2751 // The classifierInfo[Metadata] is set for the following flows
2752 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2753 // - Mcast flow that points to a group in the action/treatment
2754 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2755 // - inner vid for a double tagged packet in the datapath flow
2756 // - outer vid for a single tagged packet in the datapath flow
2757 // - inner vid in the mcast flow that points to a group
2758
2759 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2760 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2761 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2762 // 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 +00002763 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2764 vid := uint32(metadata)
2765 if vid != ReservedVlan {
2766 ivid = true
2767 }
2768 }
2769 if ovid && ivid {
2770 packetType = DoubleTag
2771 } else if !ovid && !ivid {
2772 packetType = Untagged
2773 } else {
2774 packetType = SingleTag
2775 }
2776 return packetType
2777}
2778
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002779// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002780func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002781 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002782 action := make(map[string]interface{})
2783 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2784 action[TrapToHost] = true
2785 /* We manage flowId resource pool on per PON port basis.
2786 Since this situation is tricky, as a hack, we pass the NNI port
2787 index (network_intf_id) as PON port Index for the flowId resource
2788 pool. Also, there is no ONU Id available for trapping packets
2789 on NNI port, use onu_id as -1 (invalid)
2790 ****************** CAVEAT *******************
2791 This logic works if the NNI Port Id falls within the same valid
2792 range of PON Port Ids. If this doesn't work for some OLT Vendor
2793 we need to have a re-look at this.
2794 *********************************************
2795 */
2796 onuID := -1
2797 uniID := -1
2798 gemPortID := -1
2799 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002800 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002801 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302802 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002803 "classifier": classifier,
2804 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002805 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002806 }
yasin saplibddc2d72022-02-08 13:10:17 +00002807 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002808 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002809 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002810 return nil
yasin saplid0566272021-12-21 09:10:30 +00002811 } else if err != nil {
2812 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2813 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2814 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002815 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002816
David K. Bainbridge794735f2020-02-11 21:01:37 -08002817 classifierProto, err := makeOpenOltClassifierField(classifier)
2818 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002819 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002820 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002821 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": *classifierProto})
Gamze Abaka724d0852020-03-18 12:10:24 +00002822 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002823 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002824 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002825 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002826 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": *actionProto})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002827 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2828 OnuId: int32(onuID), // OnuId not required
2829 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002830 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002831 FlowType: Downstream,
2832 AllocId: int32(allocID), // AllocId not used
2833 NetworkIntfId: int32(networkInterfaceID),
2834 GemportId: int32(gemPortID), // GemportId not used
2835 Classifier: classifierProto,
2836 Action: actionProto,
2837 Priority: int32(logicalFlow.Priority),
2838 Cookie: logicalFlow.Cookie,
2839 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002840 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002841 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow": downstreamflow}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002842 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002843 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002844
David K. Bainbridge794735f2020-02-11 21:01:37 -08002845 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002846}
2847
salmansiddiqui7ac62132019-08-22 03:58:50 +00002848func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2849 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302850 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002851 }
mgouda86543582025-10-29 20:58:16 +05302852 switch Dir {
2853 case tp_pb.Direction_UPSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002854 return "upstream", nil
mgouda86543582025-10-29 20:58:16 +05302855 case tp_pb.Direction_DOWNSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002856 return "downstream", nil
2857 }
2858 return "", nil
2859}
2860
Kent Hagermane6ff1012020-07-14 15:07:53 -04002861// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302862func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002863 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002864 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002865 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002866 intfID := args[IntfID]
2867 onuID := args[OnuID]
2868 uniID := args[UniID]
2869 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002870 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002871 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002872 gemToAes := make(map[uint32]bool)
2873
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002874 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002875 var direction = tp_pb.Direction_UPSTREAM
2876 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002877 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002878 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002879 attributes = TpInst.UpstreamGemPortAttributeList
2880 } else {
2881 attributes = TpInst.DownstreamGemPortAttributeList
2882 direction = tp_pb.Direction_DOWNSTREAM
2883 }
2884 default:
2885 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002886 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002887 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002888
2889 if len(gemPorts) == 1 {
2890 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002891 gemPortID = gemPorts[0]
2892 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002893 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2894 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002895 pBitMap := attributes[idx].PbitMap
2896 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2897 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2898 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002899 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002900 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2901 if pbitSet == pbit1 {
2902 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2903 pbitToGem[pcp] = gemID
2904 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002905 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002906 }
2907 }
2908 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002909 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2910 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2911 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002912 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002913 }
2914
Akash Kankanala041a2122024-10-16 15:49:22 +05302915 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002916
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302917 var nni_port uint32
2918 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2919 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2920 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2921 }
2922 } else {
2923 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2924 }
2925
salmansiddiqui7ac62132019-08-22 03:58:50 +00002926 if ipProto, ok := classifierInfo[IPProto]; ok {
mgouda86543582025-10-29 20:58:16 +05302927 switch ipProto.(uint32) {
2928 case IPProtoDhcp:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002929 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002930 "tp-id": tpID,
2931 "alloc-id": allocID,
2932 "intf-id": intfID,
2933 "onu-id": onuID,
2934 "uni-id": uniID,
2935 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302936 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002937 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002938 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002939 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 +05302940 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002941 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002942 }
mgouda86543582025-10-29 20:58:16 +05302943 case IgmpProto:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002944 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302945 log.Fields{
2946 "intf-id": intfID,
2947 "onu-id": onuID,
2948 "uni-id": uniID,
2949 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002950 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002951 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002952 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 +05302953 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002954 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002955 }
mgouda86543582025-10-29 20:58:16 +05302956 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002957 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002958 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002959 }
2960 } else if ethType, ok := classifierInfo[EthType]; ok {
mgouda86543582025-10-29 20:58:16 +05302961 switch ethType.(uint32) {
2962 case EapEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002963 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002964 "intf-id": intfID,
2965 "onu-id": onuID,
2966 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002967 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002968 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002969 var vlanID uint32
2970 if val, ok := classifierInfo[VlanVid]; ok {
2971 vlanID = (val.(uint32)) & VlanvIDMask
2972 } else {
2973 vlanID = DefaultMgmtVlan
2974 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002975 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002976 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002977 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 +05302978 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002979 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002980 }
mgouda86543582025-10-29 20:58:16 +05302981 case PPPoEDEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002982 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2983 "tp-id": tpID,
2984 "alloc-id": allocID,
2985 "intf-id": intfID,
2986 "onu-id": onuID,
2987 "uni-id": uniID,
2988 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302989 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002990 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002991 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002992 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 +05302993 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002994 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002995 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002996 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002997 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002998 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002999 "intf-id": intfID,
3000 "onu-id": onuID,
3001 "uni-id": uniID,
3002 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303003 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003004 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003005 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003006 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 +05303007 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003008 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003009 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003010 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003011 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003012 "intf-id": intfID,
3013 "onu-id": onuID,
3014 "uni-id": uniID,
3015 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303016 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003017 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003018 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003019 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 +05303020 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003021 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003022 }
3023 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003024 return olterrors.NewErrInvalidValue(log.Fields{
3025 "intf-id": intfID,
3026 "onu-id": onuID,
3027 "uni-id": uniID,
3028 "classifier": classifierInfo,
3029 "action": actionInfo,
3030 "flow": flow},
3031 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003032 }
3033 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003034 go func() {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003035 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, *(TpInst.(*tp_pb.TechProfileInstance))); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003036 logger.Warn(ctx, err)
3037 }
3038 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003039 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003040}
3041
Gamze Abakacb0e6772021-06-10 08:32:12 +00003042func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003043 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3044 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3045 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 +05303046 for i := 0; i < len(tpInstances); i++ {
3047 tpI := tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003048 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003049 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003050 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003051 log.Fields{
3052 "device-id": f.deviceHandler.device.Id,
3053 "intfID": sq.intfID,
3054 "onuID": sq.onuID,
3055 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003056 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003057 })
3058 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303059 }
3060 }
3061 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003062 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003063}
3064
Neha Sharma96b7bf22020-06-15 10:37:32 +00003065func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003066 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05303067 switch field.Type {
3068 case flows.ETH_TYPE:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003069 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003070 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303071 case flows.ETH_DST:
Esin Karamanccb714b2019-11-29 15:02:06 +00003072 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003073 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303074 case flows.ETH_SRC:
Girish Gowdraffa52e52022-02-16 15:48:10 -08003075 classifierInfo[EthSrc] = field.GetEthSrc()
3076 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303077 case flows.IP_PROTO:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003078 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003079 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303080 case flows.IN_PORT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003081 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003082 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303083 case flows.VLAN_VID:
Andrea Campanellafaa42152021-10-28 11:50:56 +05303084 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3085 if field.GetVlanVid() != ReservedVlan {
3086 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3087 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3088 }
mgouda86543582025-10-29 20:58:16 +05303089 case flows.VLAN_PCP:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003090 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003091 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303092 case flows.UDP_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303095 case flows.UDP_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303098 case flows.IPV4_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003099 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003100 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303101 case flows.IPV4_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003102 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003103 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303104 case flows.METADATA:
David K. Bainbridge82efc492019-09-04 09:57:11 -07003105 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303107 case flows.TUNNEL_ID:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303110 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003111 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003112 return
3113 }
3114 }
3115}
3116
Neha Sharma96b7bf22020-06-15 10:37:32 +00003117func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003118 for _, action := range flows.GetActions(flow) {
mgouda86543582025-10-29 20:58:16 +05303119 switch action.Type {
3120 case flows.OUTPUT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003121 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003122 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003123 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003124 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003125 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003126 }
mgouda86543582025-10-29 20:58:16 +05303127 case flows.POP_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003128 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003129 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303130 case flows.PUSH_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003131 if out := action.GetPush(); out != nil {
3132 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003133 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003134 } else {
3135 actionInfo[PushVlan] = true
3136 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003137 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303138 log.Fields{
3139 "push-tpid": actionInfo[TPID].(uint32),
3140 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003141 }
3142 }
mgouda86543582025-10-29 20:58:16 +05303143 case flows.SET_FIELD:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003144 if out := action.GetSetField(); out != nil {
3145 if field := out.GetField(); field != nil {
3146 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003147 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003148 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003149 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3150 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003151 }
3152 }
mgouda86543582025-10-29 20:58:16 +05303153 case flows.GROUP:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003154 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
mgouda86543582025-10-29 20:58:16 +05303155 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00003156 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003157 }
3158 }
3159 return nil
3160}
3161
Neha Sharma96b7bf22020-06-15 10:37:32 +00003162func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003163 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003164 fieldtype := ofbField.GetType()
mgouda86543582025-10-29 20:58:16 +05303165 switch fieldtype {
3166 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Esin Karamanccb714b2019-11-29 15:02:06 +00003167 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3168 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003170 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003171 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003172 }
mgouda86543582025-10-29 20:58:16 +05303173 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
Gamze Abakac43a66e2020-05-11 11:00:42 +00003174 pcp := ofbField.GetVlanPcp()
3175 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003176 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303177 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003178 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003179 }
3180 }
3181}
3182
Neha Sharma96b7bf22020-06-15 10:37:32 +00003183func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003184 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003185 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003186 } else {
3187 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003188 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003189 }
3190}
3191
Neha Sharma96b7bf22020-06-15 10:37:32 +00003192func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003193 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003194 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003195 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003196 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003197 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003198 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003199 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303200 log.Fields{
3201 "newinport": classifierInfo[InPort].(uint32),
3202 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003203 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303204 return olterrors.NewErrNotFound("child-in-port",
3205 log.Fields{
3206 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3207 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003208 }
3209 }
3210 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003211 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003212 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003213 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003214 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003215 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003216 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303217 log.Fields{
3218 "newoutport": actionInfo[Output].(uint32),
3219 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003220 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303221 return olterrors.NewErrNotFound("out-port",
3222 log.Fields{
3223 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3224 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003225 }
3226 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003227 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003228 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003229 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003230 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303231 log.Fields{
3232 "newinport": actionInfo[Output].(uint32),
3233 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003234 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303235 return olterrors.NewErrNotFound("nni-port",
3236 log.Fields{
3237 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3238 "in-port": classifierInfo[InPort].(uint32),
3239 "out-port": actionInfo[Output].(uint32),
3240 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003241 }
3242 }
3243 }
3244 return nil
3245}
Gamze Abakafee36392019-10-03 11:17:24 +00003246
Neha Sharma96b7bf22020-06-15 10:37:32 +00003247func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003248 /* Metadata 8 bytes:
3249 Most Significant 2 Bytes = Inner VLAN
3250 Next 2 Bytes = Tech Profile ID(TPID)
3251 Least Significant 4 Bytes = Port ID
3252 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3253 subscriber related flows.
3254 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003255 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003256 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003257 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003258 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003259 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003260 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003261}
3262
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003263func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003264 for _, sliceElement := range slice {
3265 if sliceElement == item {
3266 return slice
3267 }
3268 }
3269 return append(slice, item)
3270}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303271
yasin saplie87d4bd2021-12-06 09:04:03 +00003272func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3273 for _, sliceElement := range slice {
3274 if sliceElement == item {
3275 return slice
3276 }
3277 }
3278 return append(slice, item)
3279}
3280
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303281// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003282func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003283 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
mgouda86543582025-10-29 20:58:16 +05303284 switch portType {
3285 case voltha.Port_PON_OLT:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003286 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003287 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003288 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003289 log.Fields{
3290 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003291 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003292 return uint32(0), err
3293 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003294 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303295 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303296 case voltha.Port_ETHERNET_NNI:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003297 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003298 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003299 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003300 log.Fields{
3301 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003302 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003303 return uint32(0), err
3304 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003305 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303306 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303307 case voltha.Port_ETHERNET_UNI:
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303308 if _, ok := action[Output]; ok {
3309 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
3310 if err != nil {
3311 logger.Debugw(ctx, "invalid-action-port-number",
3312 log.Fields{
3313 "port-number": action[Output].(uint32),
3314 "err": err})
3315 return uint32(0), nil
3316 }
3317 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
3318 return intfID, nil
3319 } else {
3320 logger.Debugw(ctx, "action-port-number-empty",
3321 log.Fields{
3322 "action": action})
3323 return uint32(0), nil
3324 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303325 }
3326 return uint32(0), nil
3327}
3328
3329// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003330func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3331 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3332 if err != nil {
3333 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3334 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3335 return
3336 }
3337 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003338
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003339 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003340 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003341 f.packetInGemPortLock.RUnlock()
3342
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303343 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003344 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003345 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 +05303346 log.Fields{
3347 "pktinkey": pktInkey,
3348 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003349 return
3350 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303351 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003352 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003353 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003354 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003355
npujarec5762e2020-01-01 14:08:48 +05303356 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003357 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 +05303358 log.Fields{
3359 "pktinkey": pktInkey,
3360 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303361}
3362
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003363// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003364func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
mgouda86543582025-10-29 20:58:16 +05303365 if len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003366 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003367 return 0, 0, errors.New("invalid packet length")
3368 }
3369 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3370 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3371
3372 var index int8
3373 if outerEthType == 0x8100 {
3374 if innerEthType == 0x8100 {
3375 // q-in-q 802.1ad or 802.1q double tagged packet.
3376 // get the inner vlanId
3377 index = 18
3378 } else {
3379 index = 14
3380 }
3381 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303382 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003383 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3384 return vlan, priority, nil
3385 }
3386 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3387 return 0, 0, nil
3388}
3389
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003390// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003391// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003392func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003393 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003394 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3395 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003396 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003397 "flow-id": flow.Id,
3398 "device-id": f.deviceHandler.device.Id})
3399 // Remove from device
3400 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3401 // DKB
3402 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3403 log.Fields{
3404 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003405 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003406 return err
3407 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003408
3409 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003410}
3411
khenaidoodc2116e2021-10-19 17:33:19 -04003412func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003413 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003414 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003415 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003416 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003417 }
3418
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003419 switch tpInst := tpInst.(type) {
3420 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003421 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003422 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003423 DeviceId: onuDeviceID,
3424 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003425 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003426 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003427 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003428 case *tp_pb.EponTechProfileInstance:
3429 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003430 DeviceId: onuDeviceID,
3431 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003432 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003433 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003434 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003435 default:
3436 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003437 }
khenaidoodc2116e2021-10-19 17:33:19 -04003438 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003439 DeviceId: onuDeviceID,
3440 UniId: uniID,
3441 TpInstancePath: tpPath,
3442 TechTpInstance: nil,
3443 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003444}
3445
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003446// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3447func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003448 intfID := sq.intfID
3449 onuID := sq.onuID
3450 uniID := sq.uniID
3451 tpID := sq.tpID
3452
3453 var reverseDirection string
3454 if sq.direction == tp_pb.Direction_UPSTREAM {
3455 reverseDirection = "downstream"
3456 } else {
3457 reverseDirection = "upstream"
3458 }
3459
3460 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003461 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003462 return
3463 }
3464
3465 // revert-delete tech-profile instance and delete tech profile id for onu
3466 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})
3467 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3468 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003469 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003470
3471 // free gem/alloc
3472 switch techprofileInst := sq.tpInst.(type) {
3473 case *tp_pb.TechProfileInstance:
3474 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003475 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003476 }
yasin saplibddc2d72022-02-08 13:10:17 +00003477 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003478 }
3479}
3480
3481// revertSchduler is called when CreateQueues request fails
3482func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3483 // revert scheduler
3484 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 +05303485 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
3486 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003487 IntfId: sq.intfID, OnuId: sq.onuID,
3488 UniId: sq.uniID, PortNo: sq.uniPort,
3489 TrafficScheds: TrafficSched})
bseenivaa1622112025-12-11 18:24:02 +05303490 cancel()
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003491}
Girish Gowdra6071f382021-12-14 12:52:04 +05303492
3493// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3494func (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 +00003495 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303496 if err != nil {
3497 return olterrors.NewErrNotFound("meter",
3498 log.Fields{"intf-id": intfID,
3499 "onu-id": onuID,
3500 "uni-id": uniID,
3501 "device-id": f.deviceHandler.device.Id}, err)
3502 }
3503
3504 if meterInfo != nil {
3505 // If RefCnt become 0 clear the meter information from the DB.
3506 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003507 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303508 return err
3509 }
3510 } else if meterInfo.MeterID != meterID {
3511 logger.Errorw(ctx, "meter-mismatch-for-direction",
3512 log.Fields{"direction": direction,
3513 "kv-store-meter-id": meterInfo.MeterID,
3514 "meter-id-in-flow": meterID,
3515 "device-id": f.deviceHandler.device.Id})
3516 return olterrors.NewErrInvalidValue(log.Fields{
3517 "unsupported": "meter-id",
3518 "kv-store-meter-id": meterInfo.MeterID,
3519 "meter-id-in-flow": meterID,
3520 "device-id": f.deviceHandler.device.Id}, nil)
3521 }
3522 }
3523 return nil
3524}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003525
3526func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3527 /* After we successfully remove the scheduler configuration on the OLT device,
3528 * delete the meter id on the KV store.
3529 */
yasin saplibddc2d72022-02-08 13:10:17 +00003530 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003531 if err != nil {
3532 return olterrors.NewErrAdapter("unable-to-remove-meter",
3533 log.Fields{
3534 "onu": sq.onuID,
3535 "device-id": f.deviceHandler.device.Id,
3536 "intf-id": sq.intfID,
3537 "onu-id": sq.onuID,
3538 "uni-id": sq.uniID,
3539 "uni-port": sq.uniPort}, err)
3540 }
3541 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3542 log.Fields{
3543 "dir": direction,
3544 "device-id": f.deviceHandler.device.Id,
3545 "intf-id": sq.intfID,
3546 "onu-id": sq.onuID,
3547 "uni-id": sq.uniID,
3548 "uni-port": sq.uniPort})
3549 return err
3550}