blob: 640a00bf3c7d39bb7f11530102b0909e6e07c484 [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 }
bseeniva0b9cbcb2026-02-12 19:11:11 +0530398 trafficSched := f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)
399 trafficSched.TechProfileId = sq.tpID
400 TrafficSched := []*tp_pb.TrafficScheduler{trafficSched}
Girish Gowdraf3728b12022-02-02 21:46:51 -0800401
Manikkaraj kb1d51442019-07-23 10:41:02 -0400402 /* Lets make a simple assumption that if the meter-id is present on the KV store,
403 * then the scheduler and queues configuration is applied on the OLT device
404 * in the given direction.
405 */
yasin saplibddc2d72022-02-08 13:10:17 +0000406 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400407 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530408 return olterrors.NewErrNotFound("meter",
409 log.Fields{"intf-id": sq.intfID,
410 "onu-id": sq.onuID,
411 "uni-id": sq.uniID,
412 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400413 }
Girish Kumarf26e4882020-03-05 06:49:10 +0000414
Girish Gowdraf3728b12022-02-02 21:46:51 -0800415 // update reference count and return if the meter was already installed before
Girish Gowdra6071f382021-12-14 12:52:04 +0530416 if meterInfo != nil && meterInfo.MeterID == sq.meterID {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800417 logger.Infow(ctx, "scheduler-already-created-for-direction",
Girish Gowdra6071f382021-12-14 12:52:04 +0530418 log.Fields{"device-id": f.deviceHandler.device.Id, "direction": direction, "meter-id": sq.meterID})
balaji.nagarajan29be8bc2026-01-26 16:31:41 +0530419 if err = f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, meterInfo, direction, sq.onuID, sq.uniID, sq.tpID, true); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800420 return err
421 }
422
423 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); allocExists {
424 // Alloc object was already created as part of flow setup on another uni of the onu for the same service.
425 // Just create gem ports and traffic queues on the current uni for the given service
426 logger.Infow(ctx, "alloc in use on another uni, schedulers already created, creating queues only",
427 log.Fields{"intf-id": sq.intfID,
428 "onu-id": sq.onuID,
429 "uni-id": sq.uniID,
430 "tp-id": sq.tpID,
431 "device-id": f.deviceHandler.device.Id})
432 // The upstream scheduler is already created. We only need to create the queues
433 // If there are multiple upstream flows on a given uni, then it is possible that
434 // we call pushTrafficQueues multiple times, but that is OK as BAL returns OK.
435 // TODO: Find better mechanism to not duplicate request.
436 if err = f.pushTrafficQueues(ctx, sq, TrafficSched); err != nil {
437 return olterrors.NewErrAdapter("failure-pushing-traffic-queues-to-device",
438 log.Fields{"intf-id": sq.intfID,
439 "direction": sq.direction,
440 "device-id": f.deviceHandler.device.Id}, err)
441 }
442 } else {
443 logger.Infow(ctx, "alloc not in use on another uni, only meter ref cnt updated",
444 log.Fields{"intf-id": sq.intfID,
445 "onu-id": sq.onuID,
446 "uni-id": sq.uniID,
447 "tp-id": sq.tpID,
448 "device-id": f.deviceHandler.device.Id})
449 }
450 return err
Manikkaraj kb1d51442019-07-23 10:41:02 -0400451 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000452
Neha Sharma96b7bf22020-06-15 10:37:32 +0000453 logger.Debugw(ctx, "meter-does-not-exist-creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530454 log.Fields{
455 "meter-id": sq.meterID,
Girish Gowdra6071f382021-12-14 12:52:04 +0530456 "direction": direction,
Shrey Baid26912972020-04-16 21:02:31 +0530457 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000458
Girish Gowdraa482f272021-03-24 23:04:19 -0700459 found := false
460 meterInfo = &rsrcMgr.MeterInfo{}
Gamze Abakafee36392019-10-03 11:17:24 +0000461 if sq.flowMetadata != nil {
462 for _, meter := range sq.flowMetadata.Meters {
463 if sq.meterID == meter.MeterId {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700464 meterInfo.MeterID = meter.MeterId
Girish Gowdraa482f272021-03-24 23:04:19 -0700465 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 +0000466 logger.Debugw(ctx, "found-meter-config-from-flowmetadata",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700467 log.Fields{"meter": meter,
Shrey Baid26912972020-04-16 21:02:31 +0530468 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa482f272021-03-24 23:04:19 -0700469 found = true
Manikkaraj kb1d51442019-07-23 10:41:02 -0400470 break
471 }
472 }
473 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000474 logger.Errorw(ctx, "flow-metadata-not-present-in-flow", log.Fields{"device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400475 }
Girish Gowdraa482f272021-03-24 23:04:19 -0700476 if !found {
Thomas Lee S94109f12020-03-03 16:39:29 +0530477 return olterrors.NewErrNotFound("meterbands", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -0800478 "reason": "Could-not-get-meterbands-from-flowMetadata",
479 "flow-metadata": sq.flowMetadata,
Shrey Baid26912972020-04-16 21:02:31 +0530480 "meter-id": sq.meterID,
481 "device-id": f.deviceHandler.device.Id}, nil)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400482 }
Gamze Abaka01174422021-03-10 06:55:27 +0000483
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700484 if err := f.pushSchedulerQueuesToDevice(ctx, sq, TrafficSched); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530485 return olterrors.NewErrAdapter("failure-pushing-traffic-scheduler-and-queues-to-device",
486 log.Fields{"intf-id": sq.intfID,
487 "direction": sq.direction,
488 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400489 }
490
salmansiddiqui7ac62132019-08-22 03:58:50 +0000491 /* After we successfully applied the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400492 * store the meter id on the KV store, for further reference.
493 */
yasin saplibddc2d72022-02-08 13:10:17 +0000494 if err := f.resourceMgr.StoreMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID, meterInfo); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530495 return olterrors.NewErrAdapter("failed-updating-meter-id",
496 log.Fields{"onu-id": sq.onuID,
497 "meter-id": sq.meterID,
498 "device-id": f.deviceHandler.device.Id}, err)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400499 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000500 logger.Infow(ctx, "updated-meter-info-into-kv-store-successfully",
Girish Gowdra6071f382021-12-14 12:52:04 +0530501 log.Fields{"direction": direction,
Girish Gowdraa482f272021-03-24 23:04:19 -0700502 "meter-info": meterInfo,
503 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400504 return nil
505}
506
Girish Gowdraf3728b12022-02-02 21:46:51 -0800507func (f *OpenOltFlowMgr) pushTrafficQueues(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
508 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
509 if err != nil {
510 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
511 log.Fields{"intf-id": sq.intfID,
512 "direction": sq.direction,
513 "device-id": f.deviceHandler.device.Id}, err)
514 }
515 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
516 log.Fields{"direction": sq.direction,
517 "traffic-queues": trafficQueues,
518 "device-id": f.deviceHandler.device.Id})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530519 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, NetworkIntfId: sq.nniIntfID, OnuId: sq.onuID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800520 UniId: sq.uniID, PortNo: sq.uniPort,
521 TrafficQueues: trafficQueues,
522 TechProfileId: TrafficSched[0].TechProfileId}
bseenivaa1622112025-12-11 18:24:02 +0530523 subCtx1, cancel1 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
524 if _, err = f.deviceHandler.Client.CreateTrafficQueues(subCtx1, queues); err != nil {
525 cancel1()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800526 if len(queues.TrafficQueues) > 1 {
527 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 +0530528 subCtx2, cancel2 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
529 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(subCtx2, queues)
530 cancel2()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800531 }
532 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
533 }
bseenivaa1622112025-12-11 18:24:02 +0530534 cancel1()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800535 return err
536}
537
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700538func (f *OpenOltFlowMgr) pushSchedulerQueuesToDevice(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700539 trafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000540
541 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +0530542 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
543 log.Fields{"intf-id": sq.intfID,
544 "direction": sq.direction,
545 "device-id": f.deviceHandler.device.Id}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000546 }
547
Gamze Abakacb0e6772021-06-10 08:32:12 +0000548 if allocExists := f.isAllocUsedByAnotherUNI(ctx, sq); !allocExists {
549 logger.Debugw(ctx, "sending-traffic-scheduler-create-to-device",
550 log.Fields{
551 "direction": sq.direction,
552 "TrafficScheds": TrafficSched,
553 "device-id": f.deviceHandler.device.Id,
554 "intfID": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530555 "nniIntfID": sq.nniIntfID,
Gamze Abakacb0e6772021-06-10 08:32:12 +0000556 "onuID": sq.onuID,
557 "uniID": sq.uniID})
bseenivaa1622112025-12-11 18:24:02 +0530558 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
559 if _, err := f.deviceHandler.Client.CreateTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Gamze Abakacb0e6772021-06-10 08:32:12 +0000560 IntfId: sq.intfID, OnuId: sq.onuID,
561 UniId: sq.uniID, PortNo: sq.uniPort,
562 TrafficScheds: TrafficSched}); err != nil {
bseenivaa1622112025-12-11 18:24:02 +0530563 cancel()
Gamze Abakacb0e6772021-06-10 08:32:12 +0000564 return olterrors.NewErrAdapter("failed-to-create-traffic-schedulers-in-device", log.Fields{"TrafficScheds": TrafficSched}, err)
565 }
bseenivaa1622112025-12-11 18:24:02 +0530566 cancel()
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530567 logger.Debugw(ctx, "successfully-created-traffic-schedulers", log.Fields{
Gamze Abakacb0e6772021-06-10 08:32:12 +0000568 "direction": sq.direction,
569 "traffic-queues": trafficQueues,
570 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000571 }
572
573 // On receiving the CreateTrafficQueues request, the driver should create corresponding
574 // downstream queues.
Neha Sharma96b7bf22020-06-15 10:37:32 +0000575 logger.Debugw(ctx, "sending-traffic-queues-create-to-device",
Shrey Baid26912972020-04-16 21:02:31 +0530576 log.Fields{"direction": sq.direction,
577 "traffic-queues": trafficQueues,
578 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000579 queues := &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530580 NetworkIntfId: sq.nniIntfID,
581 UniId: sq.uniID, PortNo: sq.uniPort,
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000582 TrafficQueues: trafficQueues,
583 TechProfileId: TrafficSched[0].TechProfileId}
bseenivaa1622112025-12-11 18:24:02 +0530584 subCtx1, cancel1 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
585 if _, err := f.deviceHandler.Client.CreateTrafficQueues(subCtx1, queues); err != nil {
586 cancel1()
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000587 if len(queues.TrafficQueues) > 1 {
588 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 +0530589 subCtx2, cancel2 := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
590 _, _ = f.deviceHandler.Client.RemoveTrafficQueues(subCtx2, queues)
591 cancel2()
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000592 }
593 f.revertScheduler(ctx, sq, TrafficSched)
Shrey Baid26912972020-04-16 21:02:31 +0530594 return olterrors.NewErrAdapter("failed-to-create-traffic-queues-in-device", log.Fields{"traffic-queues": trafficQueues}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000595 }
bseenivaa1622112025-12-11 18:24:02 +0530596 cancel1()
Neha Sharma96b7bf22020-06-15 10:37:32 +0000597 logger.Infow(ctx, "successfully-created-traffic-schedulers", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530598 "direction": sq.direction,
599 "traffic-queues": trafficQueues,
600 "device-id": f.deviceHandler.device.Id})
Girish Kumar8f73fe02019-12-09 13:19:37 +0000601
Esin Karamanccb714b2019-11-29 15:02:06 +0000602 if sq.direction == tp_pb.Direction_DOWNSTREAM {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700603 multicastTrafficQueues := f.techprofile.GetMulticastTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance))
Esin Karamanccb714b2019-11-29 15:02:06 +0000604 if len(multicastTrafficQueues) > 0 {
Akash Kankanala041a2122024-10-16 15:49:22 +0530605 if _, present := f.grpMgr.GetInterfaceToMcastQueueMap(sq.intfID); !present { // assumed that there is only one queue per PON for the multicast service
606 // the default queue with multicastQueuePerPonPort.Priority per a pon interface is used for multicast service
607 // just put it in interfaceToMcastQueueMap to use for building group members
Neha Sharma96b7bf22020-06-15 10:37:32 +0000608 logger.Debugw(ctx, "multicast-traffic-queues", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000609 multicastQueuePerPonPort := multicastTrafficQueues[0]
Girish Gowdra9602eb42020-09-09 15:50:39 -0700610 val := &QueueInfoBrief{
Esin Karamanccb714b2019-11-29 15:02:06 +0000611 gemPortID: multicastQueuePerPonPort.GemportId,
612 servicePriority: multicastQueuePerPonPort.Priority,
613 }
Girish Gowdra9602eb42020-09-09 15:50:39 -0700614 f.grpMgr.UpdateInterfaceToMcastQueueMap(sq.intfID, val)
Akash Kankanala041a2122024-10-16 15:49:22 +0530615 // also store the queue info in kv store
yasin saplibddc2d72022-02-08 13:10:17 +0000616 if err := f.resourceMgr.AddMcastQueueForIntf(ctx, multicastQueuePerPonPort.GemportId, multicastQueuePerPonPort.Priority); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700617 logger.Errorw(ctx, "failed-to-add-mcast-queue", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400618 return err
619 }
Shrey Baid26912972020-04-16 21:02:31 +0530620
Neha Sharma96b7bf22020-06-15 10:37:32 +0000621 logger.Infow(ctx, "multicast-queues-successfully-updated", log.Fields{"device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +0000622 }
623 }
624 }
Girish Kumar8f73fe02019-12-09 13:19:37 +0000625 return nil
626}
627
Girish Gowdraf3728b12022-02-02 21:46:51 -0800628// RemoveQueues removes the traffic queues from the device based on the given schedQueue info
629func (f *OpenOltFlowMgr) RemoveQueues(ctx context.Context, sq schedQueue) error {
630 var err error
631 logger.Infow(ctx, "removing-queue-in-olt",
632 log.Fields{
633 "direction": sq.direction,
634 "intf-id": sq.intfID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530635 "nniIntfID": sq.nniIntfID,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800636 "onu-id": sq.onuID,
637 "uni-id": sq.uniID,
638 "uni-port": sq.uniPort,
639 "device-id": f.deviceHandler.device.Id})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400640
Girish Gowdraf3728b12022-02-02 21:46:51 -0800641 TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction)
642 if err != nil {
643 return olterrors.NewErrAdapter("unable-to-construct-traffic-queue-configuration",
644 log.Fields{
645 "intf-id": sq.intfID,
646 "direction": sq.direction,
647 "device-id": f.deviceHandler.device.Id}, err)
648 }
649
bseenivaa1622112025-12-11 18:24:02 +0530650 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
651 defer cancel()
652 if _, err = f.deviceHandler.Client.RemoveTrafficQueues(subCtx,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800653 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530654 NetworkIntfId: sq.nniIntfID,
655 UniId: sq.uniID, PortNo: sq.uniPort,
Girish Gowdraf3728b12022-02-02 21:46:51 -0800656 TrafficQueues: TrafficQueues,
657 TechProfileId: sq.tpID}); err != nil {
658 return olterrors.NewErrAdapter("unable-to-remove-traffic-queues-from-device",
659 log.Fields{
660 "intf-id": sq.intfID,
661 "traffic-queues": TrafficQueues,
662 "device-id": f.deviceHandler.device.Id}, err)
663 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530664 logger.Debugw(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id, "trafficQueues": TrafficQueues})
Girish Gowdraf3728b12022-02-02 21:46:51 -0800665
666 return err
667}
668
669// RemoveScheduler removes the traffic scheduler from the device based on the given schedQueue info
670func (f *OpenOltFlowMgr) RemoveScheduler(ctx context.Context, sq schedQueue) error {
Manikkaraj kb1d51442019-07-23 10:41:02 -0400671 var Direction string
672 var SchedCfg *tp_pb.SchedulerConfig
673 var err error
Girish Gowdraf3728b12022-02-02 21:46:51 -0800674 logger.Infow(ctx, "removing-scheduler-in-olt",
Shrey Baid26912972020-04-16 21:02:31 +0530675 log.Fields{
676 "direction": sq.direction,
677 "intf-id": sq.intfID,
678 "onu-id": sq.onuID,
679 "uni-id": sq.uniID,
680 "uni-port": sq.uniPort,
681 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530682 switch sq.direction {
683 case tp_pb.Direction_UPSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700684 SchedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400685 Direction = "upstream"
mgouda86543582025-10-29 20:58:16 +0530686 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700687 SchedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
Manikkaraj kb1d51442019-07-23 10:41:02 -0400688 Direction = "downstream"
689 }
690
Girish Gowdraa482f272021-03-24 23:04:19 -0700691 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 -0400692
bseeniva0b9cbcb2026-02-12 19:11:11 +0530693 trafficSched := f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), SchedCfg, TrafficShaping)
694 trafficSched.TechProfileId = sq.tpID
695 TrafficSched := []*tp_pb.TrafficScheduler{trafficSched}
Girish Kumar8f73fe02019-12-09 13:19:37 +0000696
bseenivaa1622112025-12-11 18:24:02 +0530697 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
698 if _, err = f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800699 IntfId: sq.intfID, OnuId: sq.onuID,
700 UniId: sq.uniID, PortNo: sq.uniPort,
701 TrafficScheds: TrafficSched}); err != nil {
bseenivaa1622112025-12-11 18:24:02 +0530702 cancel()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800703 return olterrors.NewErrAdapter("unable-to-remove-traffic-schedulers-from-device",
Shrey Baid26912972020-04-16 21:02:31 +0530704 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800705 "intf-id": sq.intfID,
706 "traffic-schedulers": TrafficSched,
707 "onu-id": sq.onuID,
708 "uni-id": sq.uniID,
709 "uni-port": sq.uniPort}, err)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000710 }
bseenivaa1622112025-12-11 18:24:02 +0530711 cancel()
Girish Gowdraf3728b12022-02-02 21:46:51 -0800712 logger.Infow(ctx, "removed-traffic-schedulers-successfully",
713 log.Fields{"device-id": f.deviceHandler.device.Id,
714 "intf-id": sq.intfID,
715 "onu-id": sq.onuID,
716 "uni-id": sq.uniID,
717 "uni-port": sq.uniPort})
Manikkaraj kb1d51442019-07-23 10:41:02 -0400718
Girish Gowdraf3728b12022-02-02 21:46:51 -0800719 if sq.direction == tp_pb.Direction_UPSTREAM {
720 allocID := sq.tpInst.(*tp_pb.TechProfileInstance).UsScheduler.AllocId
721 // Delete the TCONT on the ONU.
722 uni := getUniPortPath(f.deviceHandler.device.Id, sq.intfID, int32(sq.onuID), int32(sq.uniID))
yasin saplibddc2d72022-02-08 13:10:17 +0000723 tpPath := f.getTPpath(ctx, uni, sq.tpID)
Akash Kankanala041a2122024-10-16 15:49:22 +0530724 if err = f.sendDeleteTcontToChild(ctx, sq.intfID, sq.onuID, sq.uniID, allocID, tpPath); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -0800725 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Gamze Abakacb0e6772021-06-10 08:32:12 +0000726 log.Fields{
Girish Gowdraf3728b12022-02-02 21:46:51 -0800727 "intf": sq.intfID,
728 "onu-id": sq.onuID,
729 "uni-id": sq.uniID,
730 "device-id": f.deviceHandler.device.Id,
731 "alloc-id": allocID})
Gamze Abakacb0e6772021-06-10 08:32:12 +0000732 }
733 }
salmansiddiqui7ac62132019-08-22 03:58:50 +0000734
735 /* After we successfully remove the scheduler configuration on the OLT device,
Manikkaraj kb1d51442019-07-23 10:41:02 -0400736 * delete the meter id on the KV store.
737 */
Girish Gowdraf3728b12022-02-02 21:46:51 -0800738 err = f.removeMeterReference(ctx, Direction, sq)
Manikkaraj kb1d51442019-07-23 10:41:02 -0400739 return err
740}
741
Girish Gowdra197acc12021-08-16 10:59:45 -0700742// We are trying to force remove the schedulers and queues here if one exists for the given key.
743// We ignore any errors encountered in the process. The errors most likely are encountered when
744// the schedulers and queues are already cleared for the given key.
745func (f *OpenOltFlowMgr) forceRemoveSchedulerQueues(ctx context.Context, sq schedQueue) {
Girish Gowdra197acc12021-08-16 10:59:45 -0700746 var schedCfg *tp_pb.SchedulerConfig
Girish Gowdra197acc12021-08-16 10:59:45 -0700747 logger.Infow(ctx, "removing-schedulers-and-queues-in-olt",
748 log.Fields{
749 "direction": sq.direction,
750 "intf-id": sq.intfID,
751 "onu-id": sq.onuID,
752 "uni-id": sq.uniID,
753 "uni-port": sq.uniPort,
754 "tp-id": sq.tpID,
755 "device-id": f.deviceHandler.device.Id})
mgouda86543582025-10-29 20:58:16 +0530756 switch sq.direction {
757 case tp_pb.Direction_UPSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700758 schedCfg = f.techprofile.GetUsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
mgouda86543582025-10-29 20:58:16 +0530759 case tp_pb.Direction_DOWNSTREAM:
Girish Gowdra197acc12021-08-16 10:59:45 -0700760 schedCfg = f.techprofile.GetDsScheduler(sq.tpInst.(*tp_pb.TechProfileInstance))
761 }
762
763 TrafficShaping := &tp_pb.TrafficShapingInfo{} // this info is not really useful for the agent during flow removal. Just use default values.
bseeniva0b9cbcb2026-02-12 19:11:11 +0530764 trafficSched := f.techprofile.GetTrafficScheduler(sq.tpInst.(*tp_pb.TechProfileInstance), schedCfg, TrafficShaping)
765 trafficSched.TechProfileId = sq.tpID
766 TrafficSched := []*tp_pb.TrafficScheduler{trafficSched}
Girish Gowdra197acc12021-08-16 10:59:45 -0700767
768 // Remove traffic queues. Ignore any errors, just log them.
769 if TrafficQueues, err := f.techprofile.GetTrafficQueues(ctx, sq.tpInst.(*tp_pb.TechProfileInstance), sq.direction); err != nil {
770 logger.Errorw(ctx, "error retrieving traffic queue", log.Fields{
771 "direction": sq.direction,
772 "intf-id": sq.intfID,
773 "onu-id": sq.onuID,
774 "uni-id": sq.uniID,
775 "uni-port": sq.uniPort,
776 "tp-id": sq.tpID,
777 "device-id": f.deviceHandler.device.Id,
778 "err": err})
779 } else {
bseenivaa1622112025-12-11 18:24:02 +0530780 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
781 if _, err := f.deviceHandler.Client.RemoveTrafficQueues(subCtx,
Girish Gowdra197acc12021-08-16 10:59:45 -0700782 &tp_pb.TrafficQueues{IntfId: sq.intfID, OnuId: sq.onuID,
783 UniId: sq.uniID, PortNo: sq.uniPort,
784 TrafficQueues: TrafficQueues,
785 TechProfileId: TrafficSched[0].TechProfileId}); err != nil {
786 logger.Warnw(ctx, "error removing traffic queue", log.Fields{
787 "direction": sq.direction,
788 "intf-id": sq.intfID,
789 "onu-id": sq.onuID,
790 "uni-id": sq.uniID,
791 "uni-port": sq.uniPort,
792 "tp-id": sq.tpID,
793 "device-id": f.deviceHandler.device.Id,
794 "err": err})
Girish Gowdra197acc12021-08-16 10:59:45 -0700795 } else {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530796 logger.Debugw(ctx, "removed-traffic-queues-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
Girish Gowdra197acc12021-08-16 10:59:45 -0700797 "direction": sq.direction,
798 "intf-id": sq.intfID,
799 "onu-id": sq.onuID,
800 "uni-id": sq.uniID,
801 "uni-port": sq.uniPort,
802 "tp-id": sq.tpID})
803 }
bseenivaa1622112025-12-11 18:24:02 +0530804 cancel()
Girish Gowdra197acc12021-08-16 10:59:45 -0700805 }
806
bseenivaa1622112025-12-11 18:24:02 +0530807 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
Girish Gowdra197acc12021-08-16 10:59:45 -0700808 // Remove traffic schedulers. Ignore any errors, just log them.
bseenivaa1622112025-12-11 18:24:02 +0530809 if _, err := f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Girish Gowdra197acc12021-08-16 10:59:45 -0700810 IntfId: sq.intfID, OnuId: sq.onuID,
811 UniId: sq.uniID, PortNo: sq.uniPort,
812 TrafficScheds: TrafficSched}); err != nil {
813 logger.Warnw(ctx, "error removing traffic scheduler", log.Fields{
814 "direction": sq.direction,
815 "intf-id": sq.intfID,
816 "onu-id": sq.onuID,
817 "uni-id": sq.uniID,
818 "uni-port": sq.uniPort,
819 "tp-id": sq.tpID,
820 "device-id": f.deviceHandler.device.Id,
821 "err": err})
822 } else {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530823 logger.Debugw(ctx, "removed-traffic-schedulers-successfully", log.Fields{"device-id": f.deviceHandler.device.Id,
Girish Gowdra197acc12021-08-16 10:59:45 -0700824 "direction": sq.direction,
825 "intf-id": sq.intfID,
826 "onu-id": sq.onuID,
827 "uni-id": sq.uniID,
828 "uni-port": sq.uniPort,
829 "tp-id": sq.tpID})
830 }
bseenivaa1622112025-12-11 18:24:02 +0530831 cancel()
Girish Gowdra197acc12021-08-16 10:59:45 -0700832}
833
Gamze Abakafee36392019-10-03 11:17:24 +0000834// This function allocates tconts and GEM ports for an ONU
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530835func (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 +0000836 var allocIDs []uint32
837 var allgemPortIDs []uint32
manikkaraj kbf256be2019-03-25 00:13:48 +0530838 var gemPortIDs []uint32
Girish Gowdra3d633032019-12-10 16:37:05 +0530839 tpInstanceExists := false
Girish Kumar8f73fe02019-12-09 13:19:37 +0000840 var err error
yasin saplibddc2d72022-02-08 13:10:17 +0000841 allocIDs = f.resourceMgr.GetCurrentAllocIDsForOnu(ctx, onuID, uniID)
842 allgemPortIDs = f.resourceMgr.GetCurrentGEMPortIDsForOnu(ctx, onuID, uniID)
843 tpPath := f.getTPpath(ctx, uni, TpID)
Girish Gowdra54934262019-11-13 14:19:55 +0530844
Neha Sharma96b7bf22020-06-15 10:37:32 +0000845 logger.Debugw(ctx, "creating-new-tcont-and-gem", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +0530846 "intf-id": intfID,
847 "onu-id": onuID,
848 "uni-id": uniID,
849 "device-id": f.deviceHandler.device.Id,
850 "tp-id": TpID})
Girish Gowdra54934262019-11-13 14:19:55 +0530851
Manikkaraj kb1d51442019-07-23 10:41:02 -0400852 // Check tech profile instance already exists for derived port name
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700853 techProfileInstance, _ := f.techprofile.GetTPInstance(ctx, tpPath)
salmansiddiqui7ac62132019-08-22 03:58:50 +0000854 if techProfileInstance == nil {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +0530855 logger.Debugw(ctx, "tp-instance-not-found--creating-new",
Shrey Baid26912972020-04-16 21:02:31 +0530856 log.Fields{
857 "path": tpPath,
858 "device-id": f.deviceHandler.device.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700859 techProfileInstance, err = f.techprofile.CreateTechProfileInstance(ctx, TpID, uni, intfID)
Girish Kumar8f73fe02019-12-09 13:19:37 +0000860 if err != nil {
Girish Gowdra54934262019-11-13 14:19:55 +0530861 // This should not happen, something wrong in KV backend transaction
Neha Sharma96b7bf22020-06-15 10:37:32 +0000862 logger.Errorw(ctx, "tp-instance-create-failed",
Shrey Baid26912972020-04-16 21:02:31 +0530863 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700864 "err": err,
Shrey Baid26912972020-04-16 21:02:31 +0530865 "tp-id": TpID,
866 "device-id": f.deviceHandler.device.Id})
Gamze Abakafee36392019-10-03 11:17:24 +0000867 return 0, nil, nil
manikkaraj kbf256be2019-03-25 00:13:48 +0530868 }
yasin saplibddc2d72022-02-08 13:10:17 +0000869 if err := f.resourceMgr.UpdateTechProfileIDForOnu(ctx, onuID, uniID, TpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700870 logger.Warnw(ctx, "failed-to-update-tech-profile-id", log.Fields{"err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -0400871 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530872 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000873 logger.Debugw(ctx, "tech-profile-instance-already-exist-for-given port-name",
Shrey Baid26912972020-04-16 21:02:31 +0530874 log.Fields{
875 "uni": uni,
876 "device-id": f.deviceHandler.device.Id})
Girish Gowdra3d633032019-12-10 16:37:05 +0530877 tpInstanceExists = true
manikkaraj kbf256be2019-03-25 00:13:48 +0530878 }
Gamze Abakafee36392019-10-03 11:17:24 +0000879
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700880 switch tpInst := techProfileInstance.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700881 case *tp_pb.TechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700882 if UsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530883 sq := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700884 uniPort: uniPort, tpInst: techProfileInstance, meterID: UsMeterID, flowMetadata: flowMetadata}
885 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000886 logger.Errorw(ctx, "CreateSchedulerQueues-failed-upstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700887 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700888 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700889 "onu-id": onuID,
890 "uni-id": uniID,
891 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700892 "meter-id": UsMeterID,
893 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000894 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700895 return 0, nil, nil
896 }
897 }
898 if DsMeterID != 0 {
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +0530899 sq := schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, nniIntfID: nniIntfID, onuID: onuID, uniID: uniID, tpID: TpID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700900 uniPort: uniPort, tpInst: techProfileInstance, meterID: DsMeterID, flowMetadata: flowMetadata}
901 if err := f.CreateSchedulerQueues(ctx, sq); err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000902 logger.Errorw(ctx, "CreateSchedulerQueues-failed-downstream",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700903 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700904 "err": err,
Matteo Scandolo2f6b5bc2020-09-17 13:58:10 -0700905 "onu-id": onuID,
906 "uni-id": uniID,
907 "intf-id": intfID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700908 "meter-id": DsMeterID,
909 "device-id": f.deviceHandler.device.Id})
Gamze Abaka411ef2f2021-11-22 08:38:08 +0000910 f.revertTechProfileInstance(ctx, sq)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700911 return 0, nil, nil
912 }
913 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700914 allocID := tpInst.UsScheduler.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700915 for _, gem := range tpInst.UpstreamGemPortAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700916 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700917 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700918 allocIDs = appendUnique32bit(allocIDs, allocID)
Gamze Abakafee36392019-10-03 11:17:24 +0000919
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700920 if tpInstanceExists {
921 return allocID, gemPortIDs, techProfileInstance
922 }
923
924 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700925 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700926 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000927 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700928 log.Fields{
Matteo Scandolo84585372021-03-18 14:21:22 -0700929 "intf-id": intfID,
930 "onu-id": onuID,
931 "uni-id": uniID,
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700932 "alloc-ids": allocIDs,
933 "gemports": allgemPortIDs,
934 "device-id": f.deviceHandler.device.Id})
935 // Send Tconts and GEM ports to KV store
936 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
Girish Gowdra3d633032019-12-10 16:37:05 +0530937 return allocID, gemPortIDs, techProfileInstance
khenaidoodc2116e2021-10-19 17:33:19 -0400938 case *tp_pb.EponTechProfileInstance:
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700939 // CreateSchedulerQueues for EPON needs to be implemented here
940 // when voltha-protos for EPON is completed.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700941 allocID := tpInst.AllocId
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700942 for _, gem := range tpInst.UpstreamQueueAttributeList {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700943 gemPortIDs = append(gemPortIDs, gem.GemportId)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700944 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700945 allocIDs = appendUnique32bit(allocIDs, allocID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700946
947 if tpInstanceExists {
948 return allocID, gemPortIDs, techProfileInstance
949 }
950
951 for _, gemPortID := range gemPortIDs {
Girish Gowdraa09aeab2020-09-14 16:30:52 -0700952 allgemPortIDs = appendUnique32bit(allgemPortIDs, gemPortID)
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700953 }
Neha Sharma96b7bf22020-06-15 10:37:32 +0000954 logger.Infow(ctx, "allocated-tcont-and-gem-ports",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700955 log.Fields{
956 "alloc-ids": allocIDs,
957 "gemports": allgemPortIDs,
958 "device-id": f.deviceHandler.device.Id})
959 // Send Tconts and GEM ports to KV store
960 f.storeTcontsGEMPortsIntoKVStore(ctx, intfID, onuID, uniID, allocIDs, allgemPortIDs)
961 return allocID, gemPortIDs, techProfileInstance
962 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +0000963 logger.Errorw(ctx, "unknown-tech",
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -0700964 log.Fields{
965 "tpInst": tpInst})
966 return 0, nil, nil
Girish Gowdra3d633032019-12-10 16:37:05 +0530967 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530968}
969
npujarec5762e2020-01-01 14:08:48 +0530970func (f *OpenOltFlowMgr) storeTcontsGEMPortsIntoKVStore(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID []uint32, gemPortIDs []uint32) {
Neha Sharma96b7bf22020-06-15 10:37:32 +0000971 logger.Debugw(ctx, "storing-allocated-tconts-and-gem-ports-into-KV-store",
Shrey Baid26912972020-04-16 21:02:31 +0530972 log.Fields{
973 "intf-id": intfID,
974 "onu-id": onuID,
975 "uni-id": uniID,
976 "alloc-id": allocID,
977 "gemport-ids": gemPortIDs,
978 "device-id": f.deviceHandler.device.Id})
manikkaraj kbf256be2019-03-25 00:13:48 +0530979 /* Update the allocated alloc_id and gem_port_id for the ONU/UNI to KV store */
yasin saplibddc2d72022-02-08 13:10:17 +0000980 if err := f.resourceMgr.UpdateAllocIdsForOnu(ctx, onuID, uniID, allocID); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000981 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 +0530982 }
yasin saplibddc2d72022-02-08 13:10:17 +0000983 if err := f.resourceMgr.UpdateGEMPortIDsForOnu(ctx, onuID, uniID, gemPortIDs); err != nil {
yasin sapli9e4c5092022-02-01 13:52:33 +0000984 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 +0530985 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -0700986
Neha Sharma96b7bf22020-06-15 10:37:32 +0000987 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 +0530988 if err := f.resourceMgr.AddGemToOnuGemInfo(ctx, onuID, gemPortIDs); err != nil {
989 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 -0400990 }
manikkaraj kbf256be2019-03-25 00:13:48 +0530991}
992
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700993func (f *OpenOltFlowMgr) populateTechProfileForCurrentPonPort(ctx context.Context) error {
manikkaraj kbf256be2019-03-25 00:13:48 +0530994 for _, techRange := range f.resourceMgr.DevInfo.Ranges {
salmansiddiqui7ac62132019-08-22 03:58:50 +0000995 for _, intfID := range techRange.IntfIds {
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700996 if intfID == f.ponPortIdx { // initialize only for the pon port that this flow manager is managing
997 var err error
pnalmas937a24d2025-01-16 18:48:30 +0530998 f.techprofile, err = tp.NewTechProfile(ctx, intfID, f.resourceMgr.DeviceID, f.resourceMgr.PonRsrMgr, f.resourceMgr.PonRsrMgr.Backend,
Girish Gowdra4736e5c2021-08-25 15:19:10 -0700999 f.resourceMgr.PonRsrMgr.Address, f.deviceHandler.cm.Backend.PathPrefix)
1000 if err != nil || f.techprofile == nil {
1001 logger.Errorw(ctx, "failed-to-allocate-to-techprofile-for-pon-port", log.Fields{"intfID": intfID, "err": err})
1002 return fmt.Errorf("failed-to-allocate-tech-profile-for-pon-port--pon-%v-err-%v", intfID, err)
1003 }
1004 logger.Debugw(ctx, "init-tech-profile-done",
1005 log.Fields{
1006 "intf-id": intfID,
1007 "device-id": f.deviceHandler.device.Id})
1008 return nil
Girish Gowdra4c3d4602021-07-22 16:33:37 -07001009 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301010 }
1011 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07001012 logger.Errorw(ctx, "pon port not found in the the device pon port range", log.Fields{"intfID": f.ponPortIdx})
1013 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 +05301014}
1015
Gamze Abaka7650be62021-02-26 10:50:36 +00001016func (f *OpenOltFlowMgr) addUpstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001017 flowContext.classifier[PacketTagType] = SingleTag
1018 // extract the cvid/inner-vid from the write metadata
1019 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1020 if writeMetadata != 0 {
1021 // Writemetadata field is 8 bytes
1022 // cvid is on the outer most two bytes of the write metadata
1023 cvid := (writeMetadata & 0xffff000000000000) >> 48
1024 // if the cvid does not match the classifier vlan, then this indicates it is a double tagged packet
1025 if cvid != flowContext.classifier[VlanVid] && cvid != 0 {
1026 flowContext.classifier[PacketTagType] = DoubleTag
1027 }
1028 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001029 logger.Debugw(ctx, "adding-upstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301030 log.Fields{
Gamze Abaka7650be62021-02-26 10:50:36 +00001031 "uplinkClassifier": flowContext.classifier,
1032 "uplinkAction": flowContext.action})
1033 return f.addSymmetricDataPathFlow(ctx, flowContext, Upstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301034}
1035
Gamze Abaka7650be62021-02-26 10:50:36 +00001036func (f *OpenOltFlowMgr) addDownstreamDataPathFlow(ctx context.Context, flowContext *flowContext) error {
1037 downlinkClassifier := flowContext.classifier
1038 downlinkAction := flowContext.action
Girish Gowdraffa52e52022-02-16 15:48:10 -08001039 // default to single tag. If we detect an inner cvid from write-metadata, then we mark the PacketTagType as DoubleTag
1040 downlinkClassifier[PacketTagType] = SingleTag
1041 // extract the cvid/inner-vid from the write metadata
1042 writeMetadata := flows.GetMetadataFromWriteMetadataAction(ctx, flowContext.logicalFlow)
1043 if writeMetadata != 0 {
1044 // Writemetadata field is 8 bytes
1045 // cvid is on the outer most two bytes of the write metadata
1046 if cvid := (writeMetadata & 0xffff000000000000) >> 48; cvid != 0 {
1047 downlinkClassifier[PacketTagType] = DoubleTag
1048 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301049 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001050 logger.Debugw(ctx, "adding-downstream-data-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301051 log.Fields{
1052 "downlinkClassifier": downlinkClassifier,
1053 "downlinkAction": downlinkAction})
Manikkaraj kb1d51442019-07-23 10:41:02 -04001054
Girish Gowdraffa52e52022-02-16 15:48:10 -08001055 // If Pop Vlan action is specified, set the vlan to be popped from the classifier vlan match field.
1056 // The matched vlan is the one that is getting popped.
1057 if val, ok := downlinkAction[PopVlan]; ok && val.(bool) {
1058 // vlan_vid is a uint32. must be type asserted as such or conversion fails
1059 dlClVid, ok := downlinkClassifier[VlanVid].(uint32)
1060 if ok {
1061 downlinkAction[VlanVid] = dlClVid & 0xfff
1062 }
Girish Gowdra26f344b2019-10-23 14:39:13 +05301063 }
1064
Gamze Abaka7650be62021-02-26 10:50:36 +00001065 return f.addSymmetricDataPathFlow(ctx, flowContext, Downstream)
manikkaraj kbf256be2019-03-25 00:13:48 +05301066}
1067
Gamze Abaka7650be62021-02-26 10:50:36 +00001068func (f *OpenOltFlowMgr) addSymmetricDataPathFlow(ctx context.Context, flowContext *flowContext, direction string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001069 intfID := flowContext.intfID
1070 onuID := flowContext.onuID
1071 uniID := flowContext.uniID
1072 classifier := flowContext.classifier
1073 action := flowContext.action
1074 allocID := flowContext.allocID
1075 gemPortID := flowContext.gemPortID
1076 tpID := flowContext.tpID
1077 logicalFlow := flowContext.logicalFlow
Neha Sharma96b7bf22020-06-15 10:37:32 +00001078 logger.Infow(ctx, "adding-hsia-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301079 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301080 "intf-id": intfID,
1081 "onu-id": onuID,
1082 "uni-id": uniID,
1083 "device-id": f.deviceHandler.device.Id,
1084 "classifier": classifier,
1085 "action": action,
1086 "direction": direction,
1087 "alloc-id": allocID,
1088 "gemport-id": gemPortID,
1089 "flow-id": logicalFlow.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001090
yasin saplibddc2d72022-02-08 13:10:17 +00001091 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001092 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001093 logger.Infow(ctx, "flow-already-exists",
Shrey Baid26912972020-04-16 21:02:31 +05301094 log.Fields{
1095 "device-id": f.deviceHandler.device.Id,
1096 "intf-id": intfID,
1097 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001098 return nil
yasin saplid0566272021-12-21 09:10:30 +00001099 } else if err != nil {
1100 logger.Errorw(ctx, "aborting-addSymmetricDataPathFlow--flow-may-already-exist",
1101 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1102 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301103 }
yasin saplid0566272021-12-21 09:10:30 +00001104
David K. Bainbridge794735f2020-02-11 21:01:37 -08001105 classifierProto, err := makeOpenOltClassifierField(classifier)
1106 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301107 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301108 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001109 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301110 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301111 "classifier": classifierProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301112 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001113 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001114 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301115 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301116 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001117 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301118 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301119 "action": actionProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301120 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001121 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301122 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301123 return olterrors.NewErrNotFound("nni-interface-id",
David K. Bainbridge794735f2020-02-11 21:01:37 -08001124 log.Fields{
1125 "classifier": classifier,
1126 "action": action,
Shrey Baid26912972020-04-16 21:02:31 +05301127 "device-id": f.deviceHandler.device.Id,
David K. Bainbridge794735f2020-02-11 21:01:37 -08001128 }, err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301129 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001130
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001131 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001132 OnuId: int32(onuID),
1133 UniId: int32(uniID),
1134 FlowId: logicalFlow.Id,
1135 FlowType: direction,
1136 AllocId: int32(allocID),
1137 NetworkIntfId: int32(networkIntfID),
1138 GemportId: int32(gemPortID),
1139 Classifier: classifierProto,
1140 Action: actionProto,
1141 Priority: int32(logicalFlow.Priority),
1142 Cookie: logicalFlow.Cookie,
1143 PortNo: flowContext.portNo,
1144 TechProfileId: tpID,
1145 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1146 PbitToGemport: flowContext.pbitToGem,
1147 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001148 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001149 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001150 return olterrors.NewErrFlowOp("add", logicalFlow.Id, nil, err).Log()
Manikkaraj k884c1242019-04-11 16:26:42 +05301151 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001152 logger.Infow(ctx, "hsia-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301153 log.Fields{"direction": direction,
1154 "device-id": f.deviceHandler.device.Id,
bseeniva0b9cbcb2026-02-12 19:11:11 +05301155 "flow-id": flow.FlowId,
Shrey Baid26912972020-04-16 21:02:31 +05301156 "intf-id": intfID,
1157 "onu-id": onuID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001158
David K. Bainbridge794735f2020-02-11 21:01:37 -08001159 return nil
Manikkaraj k884c1242019-04-11 16:26:42 +05301160}
Esin Karamanae41e2b2019-12-17 18:13:13 +00001161
Gamze Abaka7650be62021-02-26 10:50:36 +00001162func (f *OpenOltFlowMgr) addDHCPTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001163 intfID := flowContext.intfID
1164 onuID := flowContext.onuID
1165 uniID := flowContext.uniID
1166 logicalFlow := flowContext.logicalFlow
1167 classifier := flowContext.classifier
1168 action := flowContext.action
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301169
Neha Sharma96b7bf22020-06-15 10:37:32 +00001170 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301171 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301172 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001173 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301174 "action": action,
1175 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001176 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301177 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301178
1179 // Clear the action map
1180 for k := range action {
1181 delete(action, k)
1182 }
1183
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001184 action[TrapToHost] = true
1185 classifier[UDPSrc] = uint32(68)
1186 classifier[UDPDst] = uint32(67)
1187 classifier[PacketTagType] = SingleTag
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301188
yasin saplibddc2d72022-02-08 13:10:17 +00001189 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001190 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001191 logger.Infow(ctx, "flow-exists--not-re-adding",
Shrey Baid26912972020-04-16 21:02:31 +05301192 log.Fields{
1193 "device-id": f.deviceHandler.device.Id,
1194 "intf-id": intfID,
1195 "onu-id": onuID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001196 return nil
yasin saplid0566272021-12-21 09:10:30 +00001197 } else if err != nil {
1198 logger.Errorw(ctx, "aborting-addDHCPTrapFlow--flow-may-already-exist",
1199 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1200 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301201 }
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301202
Neha Sharma96b7bf22020-06-15 10:37:32 +00001203 logger.Debugw(ctx, "creating-ul-dhcp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301204 log.Fields{
1205 "ul_classifier": classifier,
1206 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001207 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301208 "intf-id": intfID,
1209 "onu-id": onuID,
1210 "device-id": f.deviceHandler.device.Id})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301211
David K. Bainbridge794735f2020-02-11 21:01:37 -08001212 classifierProto, err := makeOpenOltClassifierField(classifier)
1213 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301214 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301215 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05301216 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": classifierProto.String()})
Gamze Abaka724d0852020-03-18 12:10:24 +00001217 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001218 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301219 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err).Log()
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301220 }
1221
David K. Bainbridge794735f2020-02-11 21:01:37 -08001222 dhcpFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001223 OnuId: int32(onuID),
1224 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001225 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001226 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001227 AllocId: int32(flowContext.allocID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001228 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001229 GemportId: int32(flowContext.gemPortID),
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301230 Classifier: classifierProto,
1231 Action: actionProto,
1232 Priority: int32(logicalFlow.Priority),
1233 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001234 PortNo: flowContext.portNo,
1235 TechProfileId: flowContext.tpID,
1236 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1237 PbitToGemport: flowContext.pbitToGem,
1238 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001239 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001240 if err := f.addFlowToDevice(ctx, logicalFlow, &dhcpFlow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05301241 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"dhcp-flow-id": dhcpFlow.FlowId}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001242 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001243 logger.Infow(ctx, "dhcp-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301244 log.Fields{
1245 "device-id": f.deviceHandler.device.Id,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001246 "flow-id": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301247 "intf-id": intfID,
1248 "onu-id": onuID})
Manjunath Vanarajuluadc57d12019-04-23 11:07:21 +05301249
David K. Bainbridge794735f2020-02-11 21:01:37 -08001250 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301251}
1252
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001253// addIGMPTrapFlow creates IGMP trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001254func (f *OpenOltFlowMgr) addIGMPTrapFlow(ctx context.Context, flowContext *flowContext) error {
1255 delete(flowContext.classifier, VlanVid)
1256 return f.addUpstreamTrapFlow(ctx, flowContext)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001257}
1258
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001259// addUpstreamTrapFlow creates a trap-to-host flow
Gamze Abaka7650be62021-02-26 10:50:36 +00001260func (f *OpenOltFlowMgr) addUpstreamTrapFlow(ctx context.Context, flowContext *flowContext) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00001261 intfID := flowContext.intfID
1262 onuID := flowContext.onuID
1263 uniID := flowContext.uniID
1264 logicalFlow := flowContext.logicalFlow
1265 classifier := flowContext.classifier
1266 action := flowContext.action
Esin Karamanae41e2b2019-12-17 18:13:13 +00001267
Neha Sharma96b7bf22020-06-15 10:37:32 +00001268 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00001269 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301270 return olterrors.NewErrNotFound("nni-interface-id",
1271 log.Fields{
1272 "classifier": classifier,
1273 "action": action,
1274 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001275 err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001276 }
1277
1278 // Clear the action map
1279 for k := range action {
1280 delete(action, k)
1281 }
1282
1283 action[TrapToHost] = true
1284 classifier[PacketTagType] = SingleTag
Esin Karamanae41e2b2019-12-17 18:13:13 +00001285
yasin saplibddc2d72022-02-08 13:10:17 +00001286 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001287 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001288 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001289 return nil
yasin saplid0566272021-12-21 09:10:30 +00001290 } else if err != nil {
1291 logger.Errorw(ctx, "aborting-addUpstreamTrapFlow--flow-may-already-exist",
1292 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1293 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00001294 }
1295
Neha Sharma96b7bf22020-06-15 10:37:32 +00001296 logger.Debugw(ctx, "creating-upstream-trap-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301297 log.Fields{
1298 "ul_classifier": classifier,
1299 "ul_action": action,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001300 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301301 "device-id": f.deviceHandler.device.Id,
1302 "intf-id": intfID,
1303 "onu-id": onuID})
Esin Karamanae41e2b2019-12-17 18:13:13 +00001304
David K. Bainbridge794735f2020-02-11 21:01:37 -08001305 classifierProto, err := makeOpenOltClassifierField(classifier)
1306 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301307 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001308 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001309 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301310 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301311 "classifier": classifierProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301312 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001313 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001314 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301315 return olterrors.NewErrInvalidValue(log.Fields{"action": action, "device-id": f.deviceHandler.device.Id}, err).Log()
Esin Karamanae41e2b2019-12-17 18:13:13 +00001316 }
1317
David K. Bainbridge794735f2020-02-11 21:01:37 -08001318 flow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001319 OnuId: int32(onuID),
1320 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001321 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00001322 FlowType: Upstream,
Gamze Abaka7650be62021-02-26 10:50:36 +00001323 AllocId: int32(flowContext.allocID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001324 NetworkIntfId: int32(networkIntfID),
Gamze Abaka7650be62021-02-26 10:50:36 +00001325 GemportId: int32(flowContext.gemPortID),
Esin Karamanae41e2b2019-12-17 18:13:13 +00001326 Classifier: classifierProto,
1327 Action: actionProto,
1328 Priority: int32(logicalFlow.Priority),
1329 Cookie: logicalFlow.Cookie,
Gamze Abaka7650be62021-02-26 10:50:36 +00001330 PortNo: flowContext.portNo,
1331 TechProfileId: flowContext.tpID,
1332 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1333 PbitToGemport: flowContext.pbitToGem,
1334 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001335 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001336
David K. Bainbridge794735f2020-02-11 21:01:37 -08001337 if err := f.addFlowToDevice(ctx, logicalFlow, &flow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05301338 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow-id": flow.FlowId, "device-id": f.deviceHandler.device.Id}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001339 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00001340
David K. Bainbridge794735f2020-02-11 21:01:37 -08001341 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00001342}
1343
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001344// Add EthType flow to device with mac, vlanId as classifier for upstream and downstream
Gamze Abaka7650be62021-02-26 10:50:36 +00001345func (f *OpenOltFlowMgr) addEthTypeBasedFlow(ctx context.Context, flowContext *flowContext, vlanID uint32, ethType uint32) error {
1346 intfID := flowContext.intfID
1347 onuID := flowContext.onuID
1348 uniID := flowContext.uniID
1349 portNo := flowContext.portNo
1350 allocID := flowContext.allocID
1351 gemPortID := flowContext.gemPortID
1352 logicalFlow := flowContext.logicalFlow
1353 classifier := flowContext.classifier
1354 action := flowContext.action
1355
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001356 logger.Infow(ctx, "adding-ethType-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301357 log.Fields{
1358 "intf-id": intfID,
1359 "onu-id": onuID,
1360 "port-no": portNo,
1361 "alloc-id": allocID,
1362 "gemport-id": gemPortID,
1363 "vlan-id": vlanID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001364 "flow": logicalFlow,
1365 "ethType": ethType})
manikkaraj kbf256be2019-03-25 00:13:48 +05301366
1367 uplinkClassifier := make(map[string]interface{})
1368 uplinkAction := make(map[string]interface{})
Girish Gowdra3d633032019-12-10 16:37:05 +05301369
manikkaraj kbf256be2019-03-25 00:13:48 +05301370 // Fill Classfier
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001371 uplinkClassifier[EthType] = ethType
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001372 uplinkClassifier[PacketTagType] = SingleTag
1373 uplinkClassifier[VlanVid] = vlanID
Gamze Abaka724d0852020-03-18 12:10:24 +00001374 uplinkClassifier[VlanPcp] = classifier[VlanPcp]
manikkaraj kbf256be2019-03-25 00:13:48 +05301375 // Fill action
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001376 uplinkAction[TrapToHost] = true
yasin saplibddc2d72022-02-08 13:10:17 +00001377 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001378 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001379 logger.Infow(ctx, "flow-exists-not-re-adding", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05301380 "device-id": f.deviceHandler.device.Id,
1381 "onu-id": onuID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001382 "intf-id": intfID,
1383 "ethType": ethType})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001384 return nil
yasin saplid0566272021-12-21 09:10:30 +00001385 } else if err != nil {
1386 logger.Errorw(ctx, "aborting-addEthTypeBasedFlow--flow-may-already-exist",
1387 log.Fields{"intf-id": intfID, "onu-id": onuID, "flow-id": logicalFlow.Id})
1388 return err
Girish Gowdra3d633032019-12-10 16:37:05 +05301389 }
Akash Kankanala041a2122024-10-16 15:49:22 +05301390 // Add Uplink EthType Flow
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001391 logger.Debugw(ctx, "creating-ul-ethType-flow",
Shrey Baid26912972020-04-16 21:02:31 +05301392 log.Fields{
1393 "ul_classifier": uplinkClassifier,
1394 "ul_action": uplinkAction,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001395 "uplinkFlowId": logicalFlow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301396 "device-id": f.deviceHandler.device.Id,
1397 "intf-id": intfID,
1398 "onu-id": onuID})
manikkaraj kbf256be2019-03-25 00:13:48 +05301399
David K. Bainbridge794735f2020-02-11 21:01:37 -08001400 classifierProto, err := makeOpenOltClassifierField(uplinkClassifier)
1401 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301402 return olterrors.NewErrInvalidValue(log.Fields{
1403 "classifier": uplinkClassifier,
1404 "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301405 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001406 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301407 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301408 "classifier": classifierProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301409 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001410 actionProto, err := makeOpenOltActionField(uplinkAction, uplinkClassifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001411 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301412 return olterrors.NewErrInvalidValue(log.Fields{"action": uplinkAction, "device-id": f.deviceHandler.device.Id}, err).Log()
manikkaraj kbf256be2019-03-25 00:13:48 +05301413 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001414 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301415 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301416 "action": actionProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301417 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001418 networkIntfID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301419 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301420 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08001421 "classifier": classifier,
Shrey Baid26912972020-04-16 21:02:31 +05301422 "action": action,
1423 "device-id": f.deviceHandler.device.Id},
David K. Bainbridge794735f2020-02-11 21:01:37 -08001424 err).Log()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05301425 }
1426
David K. Bainbridge794735f2020-02-11 21:01:37 -08001427 upstreamFlow := openoltpb2.Flow{AccessIntfId: int32(intfID),
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001428 OnuId: int32(onuID),
1429 UniId: int32(uniID),
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001430 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07001431 FlowType: Upstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001432 AllocId: int32(allocID),
1433 NetworkIntfId: int32(networkIntfID),
1434 GemportId: int32(gemPortID),
manikkaraj kbf256be2019-03-25 00:13:48 +05301435 Classifier: classifierProto,
1436 Action: actionProto,
1437 Priority: int32(logicalFlow.Priority),
1438 Cookie: logicalFlow.Cookie,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001439 PortNo: portNo,
Gamze Abaka7650be62021-02-26 10:50:36 +00001440 TechProfileId: flowContext.tpID,
1441 ReplicateFlow: len(flowContext.pbitToGem) > 0,
1442 PbitToGemport: flowContext.pbitToGem,
1443 GemportToAes: flowContext.gemToAes,
Gamze Abaka78a1d2a2020-04-27 10:17:27 +00001444 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001445 if err := f.addFlowToDevice(ctx, logicalFlow, &upstreamFlow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05301446 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow-id": upstreamFlow.FlowId}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001447 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001448 logger.Infow(ctx, "ethType-ul-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301449 log.Fields{
1450 "device-id": f.deviceHandler.device.Id,
1451 "onu-id": onuID,
1452 "intf-id": intfID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03001453 "ethType": ethType,
Shrey Baid26912972020-04-16 21:02:31 +05301454 })
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001455
David K. Bainbridge794735f2020-02-11 21:01:37 -08001456 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301457}
1458
David K. Bainbridge794735f2020-02-11 21:01:37 -08001459func makeOpenOltClassifierField(classifierInfo map[string]interface{}) (*openoltpb2.Classifier, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001460 var classifier openoltpb2.Classifier
David K. Bainbridge82efc492019-09-04 09:57:11 -07001461
1462 classifier.EthType, _ = classifierInfo[EthType].(uint32)
1463 classifier.IpProto, _ = classifierInfo[IPProto].(uint32)
1464 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
Andrea Campanella7acc0b92020-02-14 09:20:49 +01001465 if vlanID != ReservedVlan {
1466 vid := vlanID & VlanvIDMask
Harsh Awasthiea45af72019-08-26 02:39:00 -04001467 classifier.OVid = vid
1468 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301469 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07001470 // The classifierInfo[Metadata] is set for the following flows
1471 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
1472 // - Mcast flow that points to a group in the treatment
1473 // This value, when present and valid (not 0 and not 4096), is interpreted as below
1474 // - inner vid for a double tagged packet in the datapath flow
1475 // - outer vid for a single tagged packet in the datapath flow
1476 // - inner vid in the mcast flow that points to a group
David K. Bainbridge82efc492019-09-04 09:57:11 -07001477 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
1478 vid := uint32(metadata)
Andrea Campanellafaa42152021-10-28 11:50:56 +05301479 // Set the OVid or IVid classifier based on the whether OLT is using a transparent tag or not
1480 // 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 +05301481 // 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 +05301482 // becomes the IVid.
1483 if classifier.OVid != 0 && classifier.OVid != ReservedVlan { // This is case when classifier.OVid is not set
1484 if vid != ReservedVlan {
1485 classifier.IVid = vid
1486 }
1487 } else {
1488 if vid != ReservedVlan {
1489 classifier.OVid = vid
1490 }
Harsh Awasthiea45af72019-08-26 02:39:00 -04001491 }
manikkaraj kbf256be2019-03-25 00:13:48 +05301492 }
Girish Gowdrafae935c2020-02-17 19:21:44 +05301493 // Use VlanPCPMask (0xff) to signify NO PCP. Else use valid PCP (0 to 7)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001494 if vlanPcp, ok := classifierInfo[VlanPcp].(uint32); ok {
Girish Gowdrafae935c2020-02-17 19:21:44 +05301495 classifier.OPbits = vlanPcp
1496 } else {
1497 classifier.OPbits = VlanPCPMask
manikkaraj kbf256be2019-03-25 00:13:48 +05301498 }
David K. Bainbridge82efc492019-09-04 09:57:11 -07001499 classifier.SrcPort, _ = classifierInfo[UDPSrc].(uint32)
1500 classifier.DstPort, _ = classifierInfo[UDPDst].(uint32)
1501 classifier.DstIp, _ = classifierInfo[Ipv4Dst].(uint32)
1502 classifier.SrcIp, _ = classifierInfo[Ipv4Src].(uint32)
Esin Karamanccb714b2019-11-29 15:02:06 +00001503 classifier.DstMac, _ = classifierInfo[EthDst].([]uint8)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001504 classifier.SrcMac, _ = classifierInfo[EthSrc].([]uint8)
David K. Bainbridge82efc492019-09-04 09:57:11 -07001505 if pktTagType, ok := classifierInfo[PacketTagType].(string); ok {
1506 classifier.PktTagType = pktTagType
1507
1508 switch pktTagType {
1509 case SingleTag:
1510 case DoubleTag:
1511 case Untagged:
1512 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00001513 return nil, olterrors.NewErrInvalidValue(log.Fields{"packet-tag-type": pktTagType}, nil)
manikkaraj kbf256be2019-03-25 00:13:48 +05301514 }
1515 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001516 return &classifier, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301517}
1518
Akash Kankanala041a2122024-10-16 15:49:22 +05301519// nolint: unparam
1520// TODO: Improvise the function & remove the unparam lint, currently it is always returning 'nil' as error.
Gamze Abaka724d0852020-03-18 12:10:24 +00001521func makeOpenOltActionField(actionInfo map[string]interface{}, classifierInfo map[string]interface{}) (*openoltpb2.Action, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001522 var actionCmd openoltpb2.ActionCmd
1523 var action openoltpb2.Action
manikkaraj kbf256be2019-03-25 00:13:48 +05301524 action.Cmd = &actionCmd
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001525 if _, ok := actionInfo[PopVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001526 // Pop outer vid
manikkaraj kbf256be2019-03-25 00:13:48 +05301527 action.Cmd.RemoveOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001528 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001529 // Remark inner pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001530 action.Cmd.RemarkInnerPbits = true
1531 action.IPbits = actionInfo[VlanPcp].(uint32)
1532 if _, ok := actionInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001533 // Remark inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001534 action.Cmd.TranslateInnerTag = true
1535 action.IVid = actionInfo[VlanVid].(uint32)
1536 }
1537 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001538 } else if _, ok := actionInfo[PushVlan]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001539 // push outer vid
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001540 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301541 action.Cmd.AddOuterTag = true
Gamze Abaka724d0852020-03-18 12:10:24 +00001542 if _, ok := actionInfo[VlanPcp]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001543 // translate outer pbit
Gamze Abaka724d0852020-03-18 12:10:24 +00001544 action.OPbits = actionInfo[VlanPcp].(uint32)
1545 action.Cmd.RemarkOuterPbits = true
1546 if _, ok := classifierInfo[VlanVid]; ok {
Girish Gowdraffa52e52022-02-16 15:48:10 -08001547 // translate inner vid
Gamze Abaka724d0852020-03-18 12:10:24 +00001548 action.IVid = classifierInfo[VlanVid].(uint32)
1549 action.Cmd.TranslateInnerTag = true
1550 }
1551 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001552 } else if _, ok := actionInfo[TrapToHost]; ok {
1553 action.Cmd.TrapToHost = actionInfo[TrapToHost].(bool)
Girish Gowdraffa52e52022-02-16 15:48:10 -08001554 } else if _, ok := actionInfo[VlanVid]; ok {
1555 // Translate outer vid
1556 action.Cmd.TranslateOuterTag = true
1557 action.OVid = actionInfo[VlanVid].(uint32)
manikkaraj kbf256be2019-03-25 00:13:48 +05301558 }
Andrea Campanellafaa42152021-10-28 11:50:56 +05301559 // When OLT is transparent to vlans no-action is valid.
1560 /*
1561 else {
1562 return nil, olterrors.NewErrInvalidValue(log.Fields{"action-command": actionInfo}, nil)
1563 }
1564 */
David K. Bainbridge794735f2020-02-11 21:01:37 -08001565 return &action, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301566}
1567
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001568// getTPpath return the ETCD path for a given UNI port
yasin saplibddc2d72022-02-08 13:10:17 +00001569func (f *OpenOltFlowMgr) getTPpath(ctx context.Context, uniPath string, TpID uint32) string {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001570 return f.techprofile.GetTechProfileInstanceKey(ctx, TpID, uniPath)
manikkaraj kbf256be2019-03-25 00:13:48 +05301571}
1572
Gamze Abakafee36392019-10-03 11:17:24 +00001573// DeleteTechProfileInstances removes the tech profile instances from persistent storage
Girish Gowdra197acc12021-08-16 10:59:45 -07001574// We also force release scheduler and queues associated with the tp instance. Theoretically there could be
1575// an issue if the upstream scheduler (DBA) is shared across multiple UNI and we force release it, given that
1576// this function is only meant to clean up TP instances of a given UNI. But in practicality this routine
1577// is only meant to be called when the clean up of resource for the whole ONU is taking place.
1578// The reason for introducing the force cleanup of scheduler and queues (on the OLT) was introduced here
1579// because it was observed that if the ONU device was deleted too soon after the flows were
1580// unprovisioned on that ONU, the scheduler and queue removal pertinent to that ONU would remain
1581// uncleaned on the OLT. So we force clean up here and ignore any error that OLT returns during the
1582// force cleanup (possible if the OLT has already cleared those resources).
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001583func (f *OpenOltFlowMgr) DeleteTechProfileInstances(ctx context.Context, intfID uint32, onuID uint32, uniID uint32) error {
yasin saplibddc2d72022-02-08 13:10:17 +00001584 tpIDList := f.resourceMgr.GetTechProfileIDForOnu(ctx, onuID, uniID)
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001585 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
1586
Gamze Abakafee36392019-10-03 11:17:24 +00001587 for _, tpID := range tpIDList {
Girish Gowdra197acc12021-08-16 10:59:45 -07001588 // Force cleanup scheduler/queues -- start
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001589 uniPortNum := plt.MkUniPortNum(ctx, intfID, onuID, uniID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001590 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
yasin saplibddc2d72022-02-08 13:10:17 +00001591 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdra197acc12021-08-16 10:59:45 -07001592 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
1593 if err != nil || tpInst == nil { // This should not happen, something wrong in KV backend transaction
1594 logger.Warnw(ctx, "tech-profile-not-in-kv-store",
1595 log.Fields{
1596 "tp-id": tpID,
1597 "path": tpPath})
1598 }
1599 switch tpInstance := tpInst.(type) {
1600 case *tp_pb.TechProfileInstance:
1601 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1602 f.forceRemoveSchedulerQueues(ctx, schedQueue{direction: tp_pb.Direction_DOWNSTREAM, intfID: intfID, onuID: onuID, uniID: uniID, tpID: tpID, uniPort: uniPortNum, tpInst: tpInstance})
1603 }
1604 // Force cleanup scheduler/queues -- end
1605
1606 // Now remove the tp instance
npujarec5762e2020-01-01 14:08:48 +05301607 if err := f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001608 logger.Errorw(ctx, "delete-tech-profile-failed", log.Fields{"err": err, "device-id": f.deviceHandler.device.Id})
Girish Gowdra54934262019-11-13 14:19:55 +05301609 // return err
1610 // We should continue to delete tech-profile instances for other TP IDs
Gamze Abakafee36392019-10-03 11:17:24 +00001611 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001612 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 +00001613 }
1614 return nil
1615}
1616
1617// DeleteTechProfileInstance removes the tech profile instance from persistent storage
npujarec5762e2020-01-01 14:08:48 +05301618func (f *OpenOltFlowMgr) DeleteTechProfileInstance(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, uniPortName string, tpID uint32) error {
Gamze Abakafee36392019-10-03 11:17:24 +00001619 if uniPortName == "" {
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001620 uniPortName = getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
Gamze Abakafee36392019-10-03 11:17:24 +00001621 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001622 if err := f.techprofile.DeleteTechProfileInstance(ctx, tpID, uniPortName); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301623 return olterrors.NewErrAdapter("failed-to-delete-tp-instance-from-kv-store",
1624 log.Fields{
1625 "tp-id": tpID,
1626 "uni-port-name": uniPortName,
1627 "device-id": f.deviceHandler.device.Id}, err)
Devmalya Paul495b94a2019-08-27 19:42:00 -04001628 }
1629 return nil
1630}
1631
David K. Bainbridge794735f2020-02-11 21:01:37 -08001632func (f *OpenOltFlowMgr) addFlowToDevice(ctx context.Context, logicalFlow *ofp.OfpFlowStats, deviceFlow *openoltpb2.Flow) error {
Daniele Rossi22db98e2019-07-11 11:50:00 +00001633 var intfID uint32
1634 /* For flows which trap out of the NNI, the AccessIntfId is invalid
1635 (set to -1). In such cases, we need to refer to the NetworkIntfId .
1636 */
1637 if deviceFlow.AccessIntfId != -1 {
1638 intfID = uint32(deviceFlow.AccessIntfId)
1639 } else {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001640 // We need to log the valid interface ID.
1641 // 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 +00001642 intfID = uint32(deviceFlow.NetworkIntfId)
1643 }
1644
Neha Sharma96b7bf22020-06-15 10:37:32 +00001645 logger.Debugw(ctx, "sending-flow-to-device-via-grpc", log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301646 "flow-id": deviceFlow.FlowId,
Shrey Baid26912972020-04-16 21:02:31 +05301647 "device-id": f.deviceHandler.device.Id,
1648 "intf-id": intfID})
bseenivaa1622112025-12-11 18:24:02 +05301649 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1650 _, err := f.deviceHandler.Client.FlowAdd(subCtx, deviceFlow)
1651 cancel()
Daniele Rossi22db98e2019-07-11 11:50:00 +00001652
1653 st, _ := status.FromError(err)
1654 if st.Code() == codes.AlreadyExists {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001655 logger.Debug(ctx, "flow-already-exists", log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301656 "err": err,
1657 "flow-id": deviceFlow.FlowId,
1658 "device-id": f.deviceHandler.device.Id,
1659 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001660 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301661 }
Daniele Rossi22db98e2019-07-11 11:50:00 +00001662
1663 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001664 logger.Errorw(ctx, "failed-to-add-flow-to-device",
Shrey Baid26912972020-04-16 21:02:31 +05301665 log.Fields{"err": err,
bseeniva0b9cbcb2026-02-12 19:11:11 +05301666 "flow-id": deviceFlow.FlowId,
1667 "device-id": f.deviceHandler.device.Id,
1668 "intf-id": intfID})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001669 return err
Daniele Rossi22db98e2019-07-11 11:50:00 +00001670 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001671 logger.Infow(ctx, "flow-added-to-device-successfully ",
Shrey Baid26912972020-04-16 21:02:31 +05301672 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301673 "flow-id": deviceFlow.FlowId,
Shrey Baid26912972020-04-16 21:02:31 +05301674 "device-id": f.deviceHandler.device.Id,
1675 "intf-id": intfID})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001676
yasin saplid0566272021-12-21 09:10:30 +00001677 if err := f.registerFlow(ctx, logicalFlow, deviceFlow); err != nil {
1678 logger.Errorw(ctx, "failed-to-register-flow", log.Fields{"err": err})
1679 return err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001680 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08001681 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001682}
1683
Neha Sharma96b7bf22020-06-15 10:37:32 +00001684func (f *OpenOltFlowMgr) removeFlowFromDevice(ctx context.Context, deviceFlow *openoltpb2.Flow, ofFlowID uint64) error {
1685 logger.Debugw(ctx, "sending-flow-to-device-via-grpc",
Shrey Baid26912972020-04-16 21:02:31 +05301686 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301687 "flow-id": deviceFlow.FlowId,
Shrey Baid26912972020-04-16 21:02:31 +05301688 "device-id": f.deviceHandler.device.Id})
bseenivaa1622112025-12-11 18:24:02 +05301689 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
1690 _, err := f.deviceHandler.Client.FlowRemove(subCtx, deviceFlow)
1691 cancel()
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001692 if err != nil {
serkant.uluderya245caba2019-09-24 23:15:29 -07001693 if f.deviceHandler.device.ConnectStatus == common.ConnectStatus_UNREACHABLE {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001694 logger.Warnw(ctx, "can-not-remove-flow-from-device--unreachable",
Shrey Baid26912972020-04-16 21:02:31 +05301695 log.Fields{
1696 "err": err,
1697 "deviceFlow": deviceFlow,
1698 "device-id": f.deviceHandler.device.Id})
Akash Kankanala041a2122024-10-16 15:49:22 +05301699 // Assume the flow is removed
David K. Bainbridge794735f2020-02-11 21:01:37 -08001700 return nil
serkant.uluderya245caba2019-09-24 23:15:29 -07001701 }
madhumatigouda57d87be2026-06-18 14:56:28 +05301702 if e, ok := status.FromError(err); ok {
1703 if e.Code() == codes.NotFound {
1704 logger.Infow(ctx, "flow-not-found-on-device-while-removing",
1705 log.Fields{
1706 "err": err,
1707 "flow-id": deviceFlow.FlowId,
1708 "device-id": f.deviceHandler.device.Id,
1709 "cookie": deviceFlow.Cookie})
1710 return nil
1711 }
1712 }
1713 logger.Warnw(ctx, "failed-to-remove-flow-from-device", log.Fields{"err": err, "flow-id": deviceFlow.FlowId, "device-id": f.deviceHandler.device.Id, "cookie": deviceFlow.Cookie})
Girish Kumarf26e4882020-03-05 06:49:10 +00001714 return olterrors.NewErrFlowOp("remove", deviceFlow.FlowId, log.Fields{"deviceFlow": deviceFlow}, err)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04001715 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001716 logger.Infow(ctx, "flow-removed-from-device-successfully", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07001717 "of-flow-id": ofFlowID,
bseeniva0b9cbcb2026-02-12 19:11:11 +05301718 "flow-id": deviceFlow.FlowId,
Matteo Scandolo92186242020-06-12 10:54:18 -07001719 "device-id": f.deviceHandler.device.Id,
1720 })
David K. Bainbridge794735f2020-02-11 21:01:37 -08001721 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301722}
1723
David K. Bainbridge794735f2020-02-11 21:01:37 -08001724func (f *OpenOltFlowMgr) addLLDPFlow(ctx context.Context, flow *ofp.OfpFlowStats, portNo uint32) error {
Humera Kouser94d7a842019-08-25 19:04:32 -04001725 classifierInfo := make(map[string]interface{})
1726 actionInfo := make(map[string]interface{})
1727
1728 classifierInfo[EthType] = uint32(LldpEthType)
1729 classifierInfo[PacketTagType] = Untagged
1730 actionInfo[TrapToHost] = true
1731
1732 // LLDP flow is installed to trap LLDP packets on the NNI port.
1733 // We manage flow_id resource pool on per PON port basis.
1734 // Since this situation is tricky, as a hack, we pass the NNI port
1735 // index (network_intf_id) as PON port Index for the flow_id resource
1736 // pool. Also, there is no ONU Id available for trapping LLDP packets
1737 // on NNI port, use onu_id as -1 (invalid)
1738 // ****************** CAVEAT *******************
1739 // This logic works if the NNI Port Id falls within the same valid
1740 // range of PON Port Ids. If this doesn't work for some OLT Vendor
1741 // we need to have a re-look at this.
1742 // *********************************************
1743
1744 var onuID = -1
1745 var uniID = -1
1746 var gemPortID = -1
1747
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001748 networkInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, portNo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001749 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05301750 return olterrors.NewErrInvalidValue(log.Fields{"nni-port-number": portNo}, err).Log()
David K. Bainbridge794735f2020-02-11 21:01:37 -08001751 }
yasin saplibddc2d72022-02-08 13:10:17 +00001752 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00001753 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001754 logger.Infow(ctx, "flow-exists--not-re-adding", log.Fields{"device-id": f.deviceHandler.device.Id})
David K. Bainbridge794735f2020-02-11 21:01:37 -08001755 return nil
yasin saplid0566272021-12-21 09:10:30 +00001756 } else if err != nil {
1757 logger.Errorw(ctx, "aborting-addLLDPFlow--flow-may-already-exist",
1758 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
1759 return err
Humera Kouser94d7a842019-08-25 19:04:32 -04001760 }
Humera Kouser94d7a842019-08-25 19:04:32 -04001761
David K. Bainbridge794735f2020-02-11 21:01:37 -08001762 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
1763 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301764 return olterrors.NewErrInvalidValue(
1765 log.Fields{
1766 "classifier": classifierInfo,
1767 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001768 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001769 logger.Debugw(ctx, "created-classifier-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301770 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301771 "classifier": classifierProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301772 "device-id": f.deviceHandler.device.Id})
Gamze Abaka724d0852020-03-18 12:10:24 +00001773 actionProto, err := makeOpenOltActionField(actionInfo, classifierInfo)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001774 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301775 return olterrors.NewErrInvalidValue(
1776 log.Fields{
1777 "action": actionInfo,
1778 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001779 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001780 logger.Debugw(ctx, "created-action-proto",
Shrey Baid26912972020-04-16 21:02:31 +05301781 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301782 "action": actionProto.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301783 "device-id": f.deviceHandler.device.Id})
Humera Kouser94d7a842019-08-25 19:04:32 -04001784
1785 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
1786 OnuId: int32(onuID), // OnuId not required
1787 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001788 FlowId: flow.Id,
Humera Kouser94d7a842019-08-25 19:04:32 -04001789 FlowType: Downstream,
1790 NetworkIntfId: int32(networkInterfaceID),
1791 GemportId: int32(gemPortID),
1792 Classifier: classifierProto,
1793 Action: actionProto,
1794 Priority: int32(flow.Priority),
1795 Cookie: flow.Cookie,
1796 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08001797 if err := f.addFlowToDevice(ctx, flow, &downstreamflow); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001798 return olterrors.NewErrFlowOp("add", flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05301799 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301800 "flow-id": downstreamflow.FlowId,
Shrey Baid26912972020-04-16 21:02:31 +05301801 "device-id": f.deviceHandler.device.Id}, err)
Humera Kouser94d7a842019-08-25 19:04:32 -04001802 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001803 logger.Infow(ctx, "lldp-trap-on-nni-flow-added-to-device-successfully",
Shrey Baid26912972020-04-16 21:02:31 +05301804 log.Fields{
1805 "device-id": f.deviceHandler.device.Id,
1806 "onu-id": onuID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001807 "flow-id": flow.Id})
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001808
David K. Bainbridge794735f2020-02-11 21:01:37 -08001809 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301810}
1811
Matteo Scandolod625b4c2020-04-02 16:16:01 -07001812func getUniPortPath(oltID string, intfID uint32, onuID int32, uniID int32) string {
1813 return fmt.Sprintf("olt-{%s}/pon-{%d}/onu-{%d}/uni-{%d}", oltID, intfID, onuID, uniID)
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07001814}
1815
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001816// getOnuDevice to fetch onu from cache or core.
Neha Sharma96b7bf22020-06-15 10:37:32 +00001817func (f *OpenOltFlowMgr) getOnuDevice(ctx context.Context, intfID uint32, onuID uint32) (*OnuDevice, error) {
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001818 onuKey := f.deviceHandler.formOnuKey(intfID, onuID)
1819 onuDev, ok := f.deviceHandler.onus.Load(onuKey)
1820 if !ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001821 logger.Debugw(ctx, "couldnt-find-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301822 log.Fields{
1823 "intf-id": intfID,
1824 "onu-id": onuID,
1825 "device-id": f.deviceHandler.device.Id})
Neha Sharma96b7bf22020-06-15 10:37:32 +00001826 onuDevice, err := f.getChildDevice(ctx, intfID, onuID)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001827 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301828 return nil, olterrors.NewErrNotFound("onu-child-device",
1829 log.Fields{
1830 "onu-id": onuID,
1831 "intf-id": intfID,
1832 "device-id": f.deviceHandler.device.Id}, err)
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001833 }
khenaidoo106c61a2021-08-11 18:05:46 -04001834 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 +05301835 // better to ad the device to cache here.
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001836 f.deviceHandler.StoreOnuDevice(onuDev.(*OnuDevice))
1837 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001838 logger.Debugw(ctx, "found-onu-in-cache",
Shrey Baid26912972020-04-16 21:02:31 +05301839 log.Fields{
1840 "intf-id": intfID,
1841 "onu-id": onuID,
1842 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001843 }
1844
1845 return onuDev.(*OnuDevice), nil
1846}
1847
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001848// getChildDevice to fetch onu
Neha Sharma96b7bf22020-06-15 10:37:32 +00001849func (f *OpenOltFlowMgr) getChildDevice(ctx context.Context, intfID uint32, onuID uint32) (*voltha.Device, error) {
1850 logger.Infow(ctx, "GetChildDevice",
Shrey Baid26912972020-04-16 21:02:31 +05301851 log.Fields{
1852 "pon-port": intfID,
1853 "onu-id": onuID,
1854 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07001855 parentPortNo := plt.IntfIDToPortNo(intfID, voltha.Port_PON_OLT)
Neha Sharma96b7bf22020-06-15 10:37:32 +00001856 onuDevice, err := f.deviceHandler.GetChildDevice(ctx, parentPortNo, onuID)
David K. Bainbridge794735f2020-02-11 21:01:37 -08001857 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301858 return nil, olterrors.NewErrNotFound("onu",
1859 log.Fields{
1860 "interface-id": parentPortNo,
1861 "onu-id": onuID,
1862 "device-id": f.deviceHandler.device.Id},
Girish Kumarf26e4882020-03-05 06:49:10 +00001863 err)
manikkaraj kbf256be2019-03-25 00:13:48 +05301864 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001865 logger.Infow(ctx, "successfully-received-child-device-from-core",
Shrey Baid26912972020-04-16 21:02:31 +05301866 log.Fields{
1867 "device-id": f.deviceHandler.device.Id,
1868 "child_device_id": onuDevice.Id,
1869 "child_device_sn": onuDevice.SerialNumber})
Manikkaraj k884c1242019-04-11 16:26:42 +05301870 return onuDevice, nil
manikkaraj kbf256be2019-03-25 00:13:48 +05301871}
1872
Neha Sharma96b7bf22020-06-15 10:37:32 +00001873func (f *OpenOltFlowMgr) sendDeleteGemPortToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, gemPortID uint32, tpPath string) error {
1874 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301875 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001876 logger.Debugw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301877 log.Fields{
1878 "intf-id": intfID,
1879 "onu-id": onuID,
1880 "uni-id": uniID,
1881 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001882 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301883 }
1884
khenaidoodc2116e2021-10-19 17:33:19 -04001885 delGemPortMsg := &ia.DeleteGemPortMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001886 DeviceId: onuDev.deviceID,
1887 UniId: uniID,
1888 TpInstancePath: tpPath,
1889 GemPortId: gemPortID,
1890 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05301891 logger.Debugw(ctx, "sending-gem-port-delete-to-openonu-adapter", log.Fields{"msg": delGemPortMsg.String(), "child-device-id": onuDev.deviceID})
khenaidoo106c61a2021-08-11 18:05:46 -04001892
1893 if err := f.deviceHandler.sendDeleteGemPortToChildAdapter(ctx, onuDev.adapterEndpoint, delGemPortMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301894 return olterrors.NewErrCommunication("send-delete-gem-port-to-onu-adapter",
1895 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001896 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1897 "to-adapter": onuDev.adapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05301898 "onu-id": onuDev.deviceID,
1899 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001900 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301901 }
khenaidoo106c61a2021-08-11 18:05:46 -04001902
Neha Sharma96b7bf22020-06-15 10:37:32 +00001903 logger.Infow(ctx, "success-sending-del-gem-port-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301904 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001905 "msg": delGemPortMsg,
1906 "from-adapter": f.deviceHandler.device.Type,
1907 "to-adapter": onuDev.deviceType,
1908 "device-id": f.deviceHandler.device.Id,
1909 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301910 return nil
1911}
1912
Neha Sharma96b7bf22020-06-15 10:37:32 +00001913func (f *OpenOltFlowMgr) sendDeleteTcontToChild(ctx context.Context, intfID uint32, onuID uint32, uniID uint32, allocID uint32, tpPath string) error {
1914 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Girish Gowdra6b130582019-11-20 16:45:20 +05301915 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00001916 logger.Warnw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05301917 log.Fields{
1918 "intf-id": intfID,
1919 "onu-id": onuID,
1920 "uni-id": uniID,
1921 "device-id": f.deviceHandler.device.Id})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07001922 return err
Girish Gowdra6b130582019-11-20 16:45:20 +05301923 }
1924
khenaidoodc2116e2021-10-19 17:33:19 -04001925 delTcontMsg := &ia.DeleteTcontMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04001926 DeviceId: onuDev.deviceID,
1927 UniId: uniID,
1928 TpInstancePath: tpPath,
1929 AllocId: allocID,
1930 }
1931
Neha Sharma96b7bf22020-06-15 10:37:32 +00001932 logger.Debugw(ctx, "sending-tcont-delete-to-openonu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301933 log.Fields{
bseeniva0b9cbcb2026-02-12 19:11:11 +05301934 "msg": delTcontMsg.String(),
Shrey Baid26912972020-04-16 21:02:31 +05301935 "device-id": f.deviceHandler.device.Id})
khenaidoo106c61a2021-08-11 18:05:46 -04001936
1937 if err := f.deviceHandler.sendDeleteTContToChildAdapter(ctx, onuDev.adapterEndpoint, delTcontMsg); err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05301938 return olterrors.NewErrCommunication("send-delete-tcont-to-onu-adapter",
1939 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001940 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
1941 "to-adapter": onuDev.adapterEndpoint,
1942 "onu-id": onuDev.deviceID,
Shrey Baid26912972020-04-16 21:02:31 +05301943 "proxyDeviceID": onuDev.proxyDeviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04001944 "device-id": f.deviceHandler.device.Id}, err)
Girish Gowdra6b130582019-11-20 16:45:20 +05301945 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00001946 logger.Infow(ctx, "success-sending-del-tcont-to-onu-adapter",
Shrey Baid26912972020-04-16 21:02:31 +05301947 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04001948 "msg": delTcontMsg,
1949 "device-id": f.deviceHandler.device.Id,
1950 "child-device-id": onuDev.deviceID})
Girish Gowdra6b130582019-11-20 16:45:20 +05301951 return nil
1952}
1953
Joey Armstrong3f0e2422023-07-05 18:25:41 -04001954// clearResources clears pon resources in kv store and the device
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07001955// nolint: gocyclo
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001956func (f *OpenOltFlowMgr) clearResources(ctx context.Context, intfID uint32, onuID int32, uniID int32,
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05301957 flowID uint64, portNum uint32, tpID uint32, sendDeleteGemRequest bool, nniIntfID uint32) error {
Gamze Abaka745ccb72021-11-18 11:29:58 +00001958 logger.Debugw(ctx, "clearing-resources", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID, "tpID": tpID})
Gamze Abakafee36392019-10-03 11:17:24 +00001959
Girish Gowdraa482f272021-03-24 23:04:19 -07001960 uni := getUniPortPath(f.deviceHandler.device.Id, intfID, onuID, uniID)
yasin saplibddc2d72022-02-08 13:10:17 +00001961 tpPath := f.getTPpath(ctx, uni, tpID)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001962 logger.Debugw(ctx, "getting-techprofile-instance-for-subscriber",
1963 log.Fields{
1964 "tpPath": tpPath,
1965 "device-id": f.deviceHandler.device.Id})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001966
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001967 techprofileInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdra78fd63d2021-10-18 14:34:53 -07001968 if err != nil || techprofileInst == nil {
1969 // The child device is possibly deleted which in turn had cleaned up all the resources (including tp instances), check..
1970 childDevice, _ := f.getChildDevice(ctx, intfID, uint32(onuID)) // do not care about the error code
1971 if childDevice == nil {
1972 // happens when subscriber un-provision is immediately followed by child device delete
1973 // before all the flow removes are processed, the child device delete has already arrived and cleaned up all the resources
1974 logger.Warnw(ctx, "child device and its associated resources are already cleared", log.Fields{"intfID": intfID, "onuID": onuID, "uniID": uniID})
1975 return nil
1976 }
Elia Battiston2aaf4342022-02-07 15:16:38 +01001977 // If the tech profile is not found, since we want to delete it, there is no need to throw an error
1978 _ = olterrors.NewErrNotFound("tech-profile-in-kv-store",
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001979 log.Fields{
1980 "tp-id": tpID,
Elia Battiston2aaf4342022-02-07 15:16:38 +01001981 "path": tpPath}, err).Log()
1982 return nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001983 }
Gamze Abaka745ccb72021-11-18 11:29:58 +00001984
1985 var allGemPortsFree = true
Girish Gowdraa09aeab2020-09-14 16:30:52 -07001986 switch techprofileInst := techprofileInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07001987 case *tp_pb.TechProfileInstance:
Gamze Abaka745ccb72021-11-18 11:29:58 +00001988 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
1989 gemPortID := gemPort.GemportId
Girish Gowdrab4c33302022-03-18 15:07:38 -07001990 flowIDs, err := f.resourceMgr.GetFlowIDsForGem(ctx, gemPortID)
1991 if err != nil {
1992 return err
1993 }
1994 used := false
1995 for _, id := range flowIDs {
1996 if flowID != id {
1997 used = true
1998 break
yasin sapli9e4c5092022-02-01 13:52:33 +00001999 }
Girish Gowdrab4c33302022-03-18 15:07:38 -07002000 }
2001 if used {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002002 for i, flowIDinMap := range flowIDs {
2003 if flowIDinMap == flowID {
2004 flowIDs = append(flowIDs[:i], flowIDs[i+1:]...)
yasin saplibddc2d72022-02-08 13:10:17 +00002005 if err := f.resourceMgr.UpdateFlowIDsForGem(ctx, gemPortID, flowIDs); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002006 return err
2007 }
2008 break
2009 }
2010 }
2011 logger.Debugw(ctx, "gem-port-id-is-still-used-by-other-flows",
2012 log.Fields{
2013 "gemport-id": gemPortID,
2014 "usedByFlows": flowIDs,
2015 "currentFlow": flowID,
2016 "device-id": f.deviceHandler.device.Id})
2017 allGemPortsFree = false
2018 }
2019 }
2020 if !allGemPortsFree {
2021 return nil
2022 }
2023 }
2024
2025 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 -08002026
2027 // 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 +00002028 switch techprofileInst := techprofileInst.(type) {
2029 case *tp_pb.TechProfileInstance:
Girish Gowdraf3728b12022-02-02 21:46:51 -08002030 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2031 gemPortID := gemPort.GemportId
yasin saplibddc2d72022-02-08 13:10:17 +00002032 _ = f.resourceMgr.RemoveGemFromOnuGemInfo(ctx, uint32(onuID), gemPortID) // ignore error and proceed.
Girish Gowdraf3728b12022-02-02 21:46:51 -08002033
yasin saplibddc2d72022-02-08 13:10:17 +00002034 if err := f.resourceMgr.DeleteFlowIDsForGem(ctx, gemPortID); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002035 logger.Errorw(ctx, "error-removing-flow-ids-of-gem-port",
2036 log.Fields{
2037 "err": err,
2038 "intf": intfID,
2039 "onu-id": onuID,
2040 "uni-id": uniID,
2041 "device-id": f.deviceHandler.device.Id,
2042 "gemport-id": gemPortID})
2043 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002044 }
2045 // Remove queues at OLT in upstream and downstream direction
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302046 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 +05302047 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002048 logger.Warn(ctx, err)
2049 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302050 schedQ.direction = tp_pb.Direction_DOWNSTREAM
2051 if err := f.RemoveQueues(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002052 logger.Warn(ctx, err)
2053 }
2054 }
2055
2056 switch techprofileInst := techprofileInst.(type) {
2057 case *tp_pb.TechProfileInstance:
2058 // 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 +05302059 schedQ := schedQueue{direction: tp_pb.Direction_UPSTREAM, intfID: intfID, onuID: uint32(onuID), uniID: uint32(uniID), tpID: tpID, uniPort: portNum, tpInst: techprofileInst}
2060 allocExists := f.isAllocUsedByAnotherUNI(ctx, schedQ)
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002061 if !allocExists {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002062 // all alloc object references removed, remove upstream scheduler
yasin saplibddc2d72022-02-08 13:10:17 +00002063 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "upstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302064 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002065 logger.Warn(ctx, err)
2066 }
2067 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002068 // remove alloc id from resource pool by setting the 'freeFromResourcePool' to true
yasin saplibddc2d72022-02-08 13:10:17 +00002069 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, true)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002070 } else {
2071 // just remove meter reference for the upstream direction for the current pon/onu/uni
2072 // 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 +05302073 if err := f.removeMeterReference(ctx, "upstream", schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002074 return err
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002075 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002076 // setting 'freeFromResourcePool' to false in resourceMgr.FreeAllocID will only remove alloc-id data for the given pon/onu/uni
2077 // but still preserve it on the resource pool.
yasin saplibddc2d72022-02-08 13:10:17 +00002078 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.UsScheduler.AllocId, false)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002079 }
Andrea Campanella8a0d0502022-01-31 15:31:59 +01002080
Girish Gowdraf3728b12022-02-02 21:46:51 -08002081 // 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 +05302082 schedQ.direction = tp_pb.Direction_DOWNSTREAM
yasin saplibddc2d72022-02-08 13:10:17 +00002083 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, "downstream", uint32(onuID), uint32(uniID), tpID); KvStoreMeter != nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302084 if err := f.RemoveScheduler(ctx, schedQ); err != nil {
Girish Gowdraf3728b12022-02-02 21:46:51 -08002085 logger.Warn(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002086 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002087 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002088 case *tp_pb.EponTechProfileInstance:
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002089 // Delete the TCONT on the ONU.
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002090 if err := f.sendDeleteTcontToChild(ctx, intfID, uint32(onuID), uint32(uniID), techprofileInst.AllocId, tpPath); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002091 logger.Errorw(ctx, "error-processing-delete-tcont-towards-onu",
Shrey Baid26912972020-04-16 21:02:31 +05302092 log.Fields{
Girish Gowdraa482f272021-03-24 23:04:19 -07002093 "intf": intfID,
Shrey Baid26912972020-04-16 21:02:31 +05302094 "onu-id": onuID,
2095 "uni-id": uniID,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002096 "device-id": f.deviceHandler.device.Id,
khenaidoo106c61a2021-08-11 18:05:46 -04002097 "alloc-id": techprofileInst.AllocId,
2098 "error": err})
Gamze Abakafee36392019-10-03 11:17:24 +00002099 }
yasin saplibddc2d72022-02-08 13:10:17 +00002100 f.resourceMgr.FreeAllocID(ctx, uint32(onuID), uint32(uniID), techprofileInst.AllocId, true)
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302101 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2102 logger.Warn(ctx, err)
2103 }
2104 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2105 logger.Warn(ctx, err)
2106 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002107 default:
2108 logger.Errorw(ctx, "error-unknown-tech",
2109 log.Fields{
2110 "techprofileInst": techprofileInst})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002111 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002112
2113 // Free TPInstance, TPID, GemPorts and Traffic Queues. AllocID and Schedulers will be cleared later only if they are not shared across all the UNIs
2114 switch techprofileInst := techprofileInst.(type) {
2115 case *tp_pb.TechProfileInstance:
2116 for _, gemPort := range techprofileInst.UpstreamGemPortAttributeList {
2117 // Delete the gem port on the ONU.
2118 if sendDeleteGemRequest {
2119 if err := f.sendDeleteGemPortToChild(ctx, intfID, uint32(onuID), uint32(uniID), gemPort.GemportId, tpPath); err != nil {
2120 logger.Errorw(ctx, "error-processing-delete-gem-port-towards-onu",
2121 log.Fields{
2122 "err": err,
2123 "intfID": intfID,
2124 "onu-id": onuID,
2125 "uni-id": uniID,
2126 "device-id": f.deviceHandler.device.Id,
2127 "gemport-id": gemPort.GemportId})
2128 }
yasin saplibddc2d72022-02-08 13:10:17 +00002129 f.resourceMgr.FreeGemPortID(ctx, uint32(onuID), uint32(uniID), gemPort.GemportId)
Girish Gowdraf3728b12022-02-02 21:46:51 -08002130 }
2131 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302132 // Delete the tp instance and the techprofileid for onu at the end
Abhilash Laxmeshward0f58cf2022-06-01 12:15:19 +05302133 if err := f.DeleteTechProfileInstance(ctx, intfID, uint32(onuID), uint32(uniID), "", tpID); err != nil {
2134 logger.Warn(ctx, err)
2135 }
2136 if err := f.resourceMgr.RemoveTechProfileIDForOnu(ctx, uint32(onuID), uint32(uniID), tpID); err != nil {
2137 logger.Warn(ctx, err)
2138 }
Girish Gowdraf3728b12022-02-02 21:46:51 -08002139 }
2140
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302141 return nil
2142}
2143
David K. Bainbridge794735f2020-02-11 21:01:37 -08002144// nolint: gocyclo
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302145func (f *OpenOltFlowMgr) clearFlowFromDeviceAndResourceManager(ctx context.Context, flow *ofp.OfpFlowStats, flowDirection string, nni_port uint32) error {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302146 logger.Debugw(ctx, "clear-flow-from-resource-manager",
Shrey Baid26912972020-04-16 21:02:31 +05302147 log.Fields{
2148 "flowDirection": flowDirection,
bseeniva0b9cbcb2026-02-12 19:11:11 +05302149 "flow-id": flow.Id,
Shrey Baid26912972020-04-16 21:02:31 +05302150 "device-id": f.deviceHandler.device.Id})
Esin Karamanccb714b2019-11-29 15:02:06 +00002151
2152 if flowDirection == Multicast {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002153 return f.clearMulticastFlowFromResourceManager(ctx, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002154 }
2155
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302156 var ethType, ipProto, inPort uint32
2157 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05302158 switch field.Type {
2159 case flows.IP_PROTO:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302160 ipProto = field.GetIpProto()
2161 logger.Debugw(ctx, "field-type-ip-proto", log.Fields{"ipProto": ipProto})
mgouda86543582025-10-29 20:58:16 +05302162 case flows.ETH_TYPE:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302163 ethType = field.GetEthType()
2164 logger.Debugw(ctx, "field-type-eth-type", log.Fields{"ethType": ethType})
mgouda86543582025-10-29 20:58:16 +05302165 case flows.IN_PORT:
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302166 inPort = field.GetPort()
2167 logger.Debugw(ctx, "field-type-in-port", log.Fields{"inPort": inPort})
2168 }
2169 }
2170 portType := plt.IntfIDToPortTypeName(inPort)
2171 if (ethType == uint32(LldpEthType) || ipProto == uint32(IPProtoDhcp) || ipProto == uint32(IgmpProto)) &&
2172 (portType == voltha.Port_ETHERNET_NNI) {
2173 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: -1, OnuId: -1, UniId: -1, TechProfileId: 0, FlowType: Downstream}
2174 logger.Debugw(ctx, "nni-trap-flow-to-be-deleted", log.Fields{"flow": flow})
2175 return f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id)
2176 // No more processing needed for trap from nni flows.
2177 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302178
Girish Gowdra5c00ef12021-12-01 17:19:41 +05302179 portNum, Intf, onu, uni, _, _, err := plt.FlowExtractInfo(ctx, flow, flowDirection)
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302180 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002181 logger.Error(ctx, err)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002182 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302183 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002184 onuID := int32(onu)
2185 uniID := int32(uni)
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002186 tpID, err := getTpIDFromFlow(ctx, flow)
2187 if err != nil {
2188 return olterrors.NewErrNotFound("tp-id",
2189 log.Fields{
2190 "flow": flow,
2191 "intf-id": Intf,
2192 "onu-id": onuID,
2193 "uni-id": uniID,
2194 "device-id": f.deviceHandler.device.Id}, err)
2195 }
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302196
Neha Sharma96b7bf22020-06-15 10:37:32 +00002197 logger.Infow(ctx, "extracted-access-info-from-flow-to-be-deleted",
Shrey Baid26912972020-04-16 21:02:31 +05302198 log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002199 "flow-id": flow.Id,
2200 "intf-id": Intf,
Shrey Baid26912972020-04-16 21:02:31 +05302201 "onu-id": onuID,
2202 "uni-id": uniID})
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302203
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002204 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, AccessIntfId: int32(Intf), OnuId: onuID, UniId: uniID, TechProfileId: tpID, FlowType: flowDirection}
2205 logger.Debugw(ctx, "flow-to-be-deleted", log.Fields{"flow": flow})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002206 if err = f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
2207 return err
2208 }
Girish Gowdra82c80982021-03-26 16:22:02 -07002209
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302210 if err = f.clearResources(ctx, Intf, onuID, uniID, flow.Id, portNum, tpID, true, nni_port); err != nil {
Gamze Abaka745ccb72021-11-18 11:29:58 +00002211 logger.Errorw(ctx, "failed-to-clear-resources-for-flow", log.Fields{
2212 "flow-id": flow.Id,
2213 "device-id": f.deviceHandler.device.Id,
2214 "onu-id": onuID,
2215 "intf": Intf,
2216 "err": err,
2217 })
2218 return err
Abhilash Laxmeshwarb7300fe2019-11-13 03:38:33 +05302219 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002220
Girish Gowdra82c80982021-03-26 16:22:02 -07002221 // 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 +05302222 if err := f.resourceMgr.HandleMeterInfoRefCntUpdate(ctx, nil, flowDirection, uint32(onuID), uint32(uniID), tpID, false); err != nil {
Girish Gowdra82c80982021-03-26 16:22:02 -07002223 return err
2224 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002225 return nil
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002226}
2227
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002228// RemoveFlow removes the flow from the device
Girish Gowdracefae192020-03-19 18:14:10 -07002229func (f *OpenOltFlowMgr) RemoveFlow(ctx context.Context, flow *ofp.OfpFlowStats) error {
bseeniva0b9cbcb2026-02-12 19:11:11 +05302230 logger.Debugw(ctx, "removing-flow", log.Fields{"flow-id": flow.Id})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302231 var direction string
2232 actionInfo := make(map[string]interface{})
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002233
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302234 for _, action := range flows.GetActions(flow) {
2235 if action.Type == flows.OUTPUT {
2236 if out := action.GetOutput(); out != nil {
2237 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002238 logger.Debugw(ctx, "action-type-output", log.Fields{"out_port": actionInfo[Output].(uint32)})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302239 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002240 logger.Error(ctx, "invalid-output-port-in-action")
Girish Gowdracefae192020-03-19 18:14:10 -07002241 return olterrors.NewErrInvalidValue(log.Fields{"invalid-out-port-action": 0}, nil)
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002242 }
2243 }
2244 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002245
2246 if flows.HasGroup(flow) {
2247 direction = Multicast
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002248 } else if plt.IsUpstream(actionInfo[Output].(uint32)) {
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302249 direction = Upstream
2250 } else {
2251 direction = Downstream
2252 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302253
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302254 var nni_port uint32
2255 if direction == Upstream {
2256 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2257 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2258 }
2259 } else {
2260 classifierInfo := make(map[string]interface{})
2261 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
2262 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2263 }
2264
Girish Gowdracefae192020-03-19 18:14:10 -07002265 // Serialize flow removes on a per subscriber basis
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302266 err := f.clearFlowFromDeviceAndResourceManager(ctx, flow, direction, nni_port)
Girish Gowdracefae192020-03-19 18:14:10 -07002267
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002268 return err
Manjunath Vanarajulu28c3e822019-05-16 11:14:28 -04002269}
2270
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002271// isIgmpTrapDownstreamFlow return true if the flow is a downsteam IGMP trap-to-host flow; false otherwise
Esin Karamanae41e2b2019-12-17 18:13:13 +00002272func isIgmpTrapDownstreamFlow(classifierInfo map[string]interface{}) bool {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002273 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_ETHERNET_NNI {
Esin Karamanae41e2b2019-12-17 18:13:13 +00002274 if ethType, ok := classifierInfo[EthType]; ok {
2275 if ethType.(uint32) == IPv4EthType {
2276 if ipProto, ok := classifierInfo[IPProto]; ok {
2277 if ipProto.(uint32) == IgmpProto {
2278 return true
2279 }
2280 }
2281 }
2282 }
2283 }
2284 return false
2285}
2286
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002287// RouteFlowToOnuChannel routes incoming flow to ONU specific channel
khenaidoodc2116e2021-10-19 17:33:19 -04002288func (f *OpenOltFlowMgr) RouteFlowToOnuChannel(ctx context.Context, flow *ofp.OfpFlowStats, addFlow bool, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002289 if f.deviceHandler.getDeviceDeletionInProgressFlag() {
2290 // The device itself is going to be reset as part of deletion. So nothing to be done.
2291 logger.Infow(ctx, "device-deletion-in-progress--not-handling-flows-or-groups", log.Fields{"device-id": f.deviceHandler.device.Id})
2292 return nil
2293 }
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002294 // Step1 : Fill flowControlBlock
2295 // Step2 : Push the flowControlBlock to ONU channel
2296 // Step3 : Wait on response channel for response
2297 // Step4 : Return error value
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002298 startTime := time.Now()
2299 logger.Infow(ctx, "process-flow", log.Fields{"flow": flow, "addFlow": addFlow})
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002300 errChan := make(chan error)
2301 flowCb := flowControlBlock{
2302 ctx: ctx,
2303 addFlow: addFlow,
2304 flow: flow,
2305 flowMetadata: flowMetadata,
2306 errChan: &errChan,
2307 }
2308 inPort, outPort := getPorts(flow)
2309 var onuID uint32
2310 if inPort != InvalidPort && outPort != InvalidPort {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002311 _, _, onuID, _ = plt.ExtractAccessFromFlow(inPort, outPort)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002312 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002313 if f.flowHandlerRoutineActive[onuID] {
2314 // inPort or outPort is InvalidPort for trap-from-nni flows.
2315 // In the that case onuID is 0 which is the reserved index for trap-from-nni flows in the f.incomingFlows slice
2316 // Send the flowCb on the ONU flow channel
2317 f.incomingFlows[onuID] <- flowCb
2318 // Wait on the channel for flow handlers return value
2319 err := <-errChan
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302320 logger.Debugw(ctx, "process-flow-received-resp", log.Fields{"err": err, "totalTimeSeconds": time.Since(startTime).Seconds()})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002321 return err
2322 }
2323 logger.Errorw(ctx, "flow handler routine not active for onu", log.Fields{"onuID": onuID, "ponPortIdx": f.ponPortIdx})
2324 return fmt.Errorf("flow-handler-routine-not-active-for-onu-%v-pon-%d", onuID, f.ponPortIdx)
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002325}
2326
2327// This routine is unique per ONU ID and blocks on flowControlBlock channel for incoming flows
2328// 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 -07002329func (f *OpenOltFlowMgr) perOnuFlowHandlerRoutine(handlerRoutineIndex int, subscriberFlowChannel chan flowControlBlock, stopHandler chan bool) {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002330 var flowCb flowControlBlock
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002331 for {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002332 select {
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002333 // block on the channel to receive an incoming flow
2334 // process the flow completely before proceeding to handle the next flow
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002335 case flowCb = <-subscriberFlowChannel:
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002336 if flowCb.addFlow {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302337 logger.Debug(flowCb.ctx, "adding-flow-start")
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002338 startTime := time.Now()
2339 err := f.AddFlow(flowCb.ctx, flowCb.flow, flowCb.flowMetadata)
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302340 logger.Infow(flowCb.ctx, "adding-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds(), "flow": flowCb.flow})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002341 // Pass the return value over the return channel
2342 *flowCb.errChan <- err
2343 } else {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302344 logger.Debug(flowCb.ctx, "removing-flow-start")
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002345 startTime := time.Now()
2346 err := f.RemoveFlow(flowCb.ctx, flowCb.flow)
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302347 logger.Infow(flowCb.ctx, "removing-flow-complete", log.Fields{"processTimeSecs": time.Since(startTime).Seconds(), "flow": flowCb.flow})
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002348 // Pass the return value over the return channel
2349 *flowCb.errChan <- err
2350 }
2351 case <-stopHandler:
2352 f.flowHandlerRoutineActive[handlerRoutineIndex] = false
2353 return
Girish Gowdrafb3d6102020-10-16 16:32:36 -07002354 }
2355 }
2356}
2357
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002358// StopAllFlowHandlerRoutines stops all flow handler routines. Call this when device is being rebooted or deleted
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002359func (f *OpenOltFlowMgr) StopAllFlowHandlerRoutines(ctx context.Context, wg *sync.WaitGroup) {
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002360 for i, v := range f.stopFlowHandlerRoutine {
2361 if f.flowHandlerRoutineActive[i] {
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002362 select {
2363 case v <- true:
2364 case <-time.After(time.Second * 5):
2365 logger.Warnw(ctx, "timeout stopping flow handler routine", log.Fields{"onuID": i, "deviceID": f.deviceHandler.device.Id})
2366 }
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002367 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002368 f.stopFlowHandlerRoutine[i] = nil
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002369 }
Holger Hildebrandt143b5be2023-02-10 08:28:15 +00002370 f.stopFlowHandlerRoutine = nil
2371
2372 if f.incomingFlows != nil {
2373 for k := range f.incomingFlows {
2374 if f.incomingFlows[k] != nil {
2375 f.incomingFlows[k] = nil
2376 }
2377 }
2378 f.incomingFlows = nil
2379 }
2380
Girish Gowdra20e3dcd2021-11-18 22:56:49 -08002381 wg.Done()
Girish Gowdra4736e5c2021-08-25 15:19:10 -07002382 logger.Debugw(ctx, "stopped all flow handler routines", log.Fields{"ponPortIdx": f.ponPortIdx})
2383}
2384
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002385// AddFlow add flow to device
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302386// nolint: gocyclo
khenaidoodc2116e2021-10-19 17:33:19 -04002387func (f *OpenOltFlowMgr) AddFlow(ctx context.Context, flow *ofp.OfpFlowStats, flowMetadata *ofp.FlowMetadata) error {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002388 classifierInfo := make(map[string]interface{})
2389 actionInfo := make(map[string]interface{})
Manikkaraj kb1d51442019-07-23 10:41:02 -04002390 var UsMeterID uint32
2391 var DsMeterID uint32
2392
Neha Sharma96b7bf22020-06-15 10:37:32 +00002393 logger.Infow(ctx, "adding-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302394 log.Fields{
2395 "flow": flow,
Matteo Scandolof16389e2021-05-18 00:47:08 +00002396 "flowmetadata": flowMetadata})
Neha Sharma96b7bf22020-06-15 10:37:32 +00002397 formulateClassifierInfoFromFlow(ctx, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002398
Neha Sharma96b7bf22020-06-15 10:37:32 +00002399 err := formulateActionInfoFromFlow(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002400 if err != nil {
2401 // Error logging is already done in the called function
2402 // So just return in case of error
Andrea Campanellac63bba92020-03-10 17:01:04 +01002403 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302404 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002405
Esin Karamanccb714b2019-11-29 15:02:06 +00002406 if flows.HasGroup(flow) {
2407 // handle multicast flow
Andrea Campanellac63bba92020-03-10 17:01:04 +01002408 return f.handleFlowWithGroup(ctx, actionInfo, classifierInfo, flow)
Esin Karamanccb714b2019-11-29 15:02:06 +00002409 }
2410
manikkaraj k17652a72019-05-06 09:06:36 -04002411 /* Controller bound trap flows */
Neha Sharma96b7bf22020-06-15 10:37:32 +00002412 err = formulateControllerBoundTrapFlowInfo(ctx, actionInfo, classifierInfo, flow)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002413 if err != nil {
2414 // error if any, already logged in the called function
Andrea Campanellac63bba92020-03-10 17:01:04 +01002415 return err
manikkaraj k17652a72019-05-06 09:06:36 -04002416 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00002417
Neha Sharma96b7bf22020-06-15 10:37:32 +00002418 logger.Debugw(ctx, "flow-ports",
Shrey Baid26912972020-04-16 21:02:31 +05302419 log.Fields{
2420 "classifierinfo_inport": classifierInfo[InPort],
2421 "action_output": actionInfo[Output]})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002422 portNo, intfID, onuID, uniID := plt.ExtractAccessFromFlow(classifierInfo[InPort].(uint32), actionInfo[Output].(uint32))
A R Karthick1f85b802019-10-11 05:06:05 +00002423
Humera Kouser94d7a842019-08-25 19:04:32 -04002424 if ethType, ok := classifierInfo[EthType]; ok {
2425 if ethType.(uint32) == LldpEthType {
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302426 logger.Debug(ctx, "adding-lldp-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002427 return f.addLLDPFlow(ctx, flow, portNo)
Humera Kouser94d7a842019-08-25 19:04:32 -04002428 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002429 if ethType.(uint32) == PPPoEDEthType {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002430 if voltha.Port_ETHERNET_NNI == plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)) {
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002431 logger.Debug(ctx, "trap-pppoed-from-nni-flow")
2432 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
2433 }
2434 }
Humera Kouser94d7a842019-08-25 19:04:32 -04002435 }
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002436 if ipProto, ok := classifierInfo[IPProto]; ok {
2437 if ipProto.(uint32) == IPProtoDhcp {
2438 if udpSrc, ok := classifierInfo[UDPSrc]; ok {
Naga Manjunathb8438aa2020-01-02 17:52:33 +05302439 if udpSrc.(uint32) == uint32(67) || udpSrc.(uint32) == uint32(546) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002440 logger.Debug(ctx, "trap-dhcp-from-nni-flow")
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002441 return f.addTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002442 }
2443 }
2444 }
2445 }
Esin Karamanae41e2b2019-12-17 18:13:13 +00002446 if isIgmpTrapDownstreamFlow(classifierInfo) {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002447 logger.Debug(ctx, "trap-igmp-from-nni-flow")
Andrea Campanellac63bba92020-03-10 17:01:04 +01002448 return f.addIgmpTrapFlowOnNNI(ctx, flow, classifierInfo, portNo)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002449 }
A R Karthick1f85b802019-10-11 05:06:05 +00002450
yasin saplibddc2d72022-02-08 13:10:17 +00002451 f.resourceMgr.AddUniPortToOnuInfo(ctx, onuID, portNo)
A R Karthick1f85b802019-10-11 05:06:05 +00002452
Girish Gowdra6071f382021-12-14 12:52:04 +05302453 tpID, err := getTpIDFromFlow(ctx, flow)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002454 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302455 return olterrors.NewErrNotFound("tpid-for-flow",
2456 log.Fields{
2457 "flow": flow,
2458 "intf-id": IntfID,
2459 "onu-id": onuID,
2460 "uni-id": uniID}, err)
Chaitrashree G S90a17952019-11-14 21:51:21 -05002461 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002462 logger.Debugw(ctx, "tpid-for-this-subcriber",
Shrey Baid26912972020-04-16 21:02:31 +05302463 log.Fields{
Girish Gowdra6071f382021-12-14 12:52:04 +05302464 "tp-id": tpID,
Shrey Baid26912972020-04-16 21:02:31 +05302465 "intf-id": intfID,
2466 "onu-id": onuID,
2467 "uni-id": uniID})
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002468 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Scott Baker355d1742019-10-24 10:57:52 -07002469 UsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002470 logger.Debugw(ctx, "upstream-flow-meter-id", log.Fields{"us-meter-id": UsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302471 if err := f.validateMeter(ctx, Upstream, UsMeterID, intfID, onuID, uniID, tpID); err != nil {
2472 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2473 return err
2474 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002475 } else {
Scott Baker355d1742019-10-24 10:57:52 -07002476 DsMeterID = flows.GetMeterIdFromFlow(flow)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002477 logger.Debugw(ctx, "downstream-flow-meter-id", log.Fields{"ds-meter-id": DsMeterID})
Girish Gowdra6071f382021-12-14 12:52:04 +05302478 if err := f.validateMeter(ctx, Downstream, DsMeterID, intfID, onuID, uniID, tpID); err != nil {
2479 logger.Errorw(ctx, "meter-validation-failed", log.Fields{"err": err})
2480 return err
2481 }
Manikkaraj kb1d51442019-07-23 10:41:02 -04002482 }
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302483
2484 var nni_port uint32
2485 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2486 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2487 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2488 }
2489 } else {
2490 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4
2491 }
2492
2493 return f.processAddFlow(ctx, intfID, nni_port, onuID, uniID, portNo, classifierInfo, actionInfo, flow, tpID, UsMeterID, DsMeterID, flowMetadata)
Girish Gowdra9602eb42020-09-09 15:50:39 -07002494}
Girish Gowdra3d633032019-12-10 16:37:05 +05302495
Esin Karamanccb714b2019-11-29 15:02:06 +00002496// handleFlowWithGroup adds multicast flow to the device.
David K. Bainbridge794735f2020-02-11 21:01:37 -08002497func (f *OpenOltFlowMgr) handleFlowWithGroup(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Himani Chawlab6296c42021-10-28 11:50:56 +05302498 classifierInfo[PacketTagType] = getPacketTypeFromClassifiers(classifierInfo)
Neha Sharma96b7bf22020-06-15 10:37:32 +00002499 logger.Debugw(ctx, "add-multicast-flow", log.Fields{
Shrey Baid26912972020-04-16 21:02:31 +05302500 "classifier-info": classifierInfo,
2501 "actionInfo": actionInfo})
Esin Karamanccb714b2019-11-29 15:02:06 +00002502
Esin Karaman65409d82020-03-18 10:58:18 +00002503 networkInterfaceID, err := f.getNNIInterfaceIDOfMulticastFlow(ctx, classifierInfo)
Esin Karamanccb714b2019-11-29 15:02:06 +00002504 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002505 return olterrors.NewErrNotFound("multicast-in-port", log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002506 }
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002507
Esin Karamanfcddfcf2020-03-04 13:34:38 +00002508 delete(classifierInfo, EthType)
Esin Karamanccb714b2019-11-29 15:02:06 +00002509
David K. Bainbridge794735f2020-02-11 21:01:37 -08002510 onuID := NoneOnuID
Esin Karamanccb714b2019-11-29 15:02:06 +00002511
yasin saplibddc2d72022-02-08 13:10:17 +00002512 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), flow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002513 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002514 logger.Infow(ctx, "multicast-flow-exists-not-re-adding", log.Fields{"classifier-info": classifierInfo})
David K. Bainbridge794735f2020-02-11 21:01:37 -08002515 return nil
yasin saplid0566272021-12-21 09:10:30 +00002516 } else if err != nil {
2517 logger.Errorw(ctx, "aborting-handleFlowWithGroup--flow-may-already-exist",
2518 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": flow.Id})
2519 return err
Esin Karamanccb714b2019-11-29 15:02:06 +00002520 }
yasin saplid0566272021-12-21 09:10:30 +00002521
David K. Bainbridge794735f2020-02-11 21:01:37 -08002522 classifierProto, err := makeOpenOltClassifierField(classifierInfo)
2523 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002524 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002525 }
2526 groupID := actionInfo[GroupID].(uint32)
2527 multicastFlow := openoltpb2.Flow{
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002528 FlowId: flow.Id,
Esin Karamanccb714b2019-11-29 15:02:06 +00002529 FlowType: Multicast,
2530 NetworkIntfId: int32(networkInterfaceID),
2531 GroupId: groupID,
2532 Classifier: classifierProto,
2533 Priority: int32(flow.Priority),
2534 Cookie: flow.Cookie}
2535
Kent Hagermane6ff1012020-07-14 15:07:53 -04002536 if err := f.addFlowToDevice(ctx, flow, &multicastFlow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05302537 return olterrors.NewErrFlowOp("add", flow.Id, log.Fields{"flow-id": multicastFlow.FlowId}, err)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002538 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002539 logger.Info(ctx, "multicast-flow-added-to-device-successfully")
Akash Kankanala041a2122024-10-16 15:49:22 +05302540 // get cached group
Girish Gowdra9602eb42020-09-09 15:50:39 -07002541 if group, _, err := f.grpMgr.getFlowGroupFromKVStore(ctx, groupID, true); err == nil {
Akash Kankanala041a2122024-10-16 15:49:22 +05302542 // calling groupAdd to set group members after multicast flow creation
Girish Gowdra9602eb42020-09-09 15:50:39 -07002543 if err := f.grpMgr.ModifyGroup(ctx, group); err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002544 return olterrors.NewErrGroupOp("modify", groupID, log.Fields{"group": group}, err)
Esin Karamanccb714b2019-11-29 15:02:06 +00002545 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302546 // cached group can be removed now
Kent Hagermane6ff1012020-07-14 15:07:53 -04002547 if err := f.resourceMgr.RemoveFlowGroupFromKVStore(ctx, groupID, true); err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002548 logger.Warnw(ctx, "failed-to-remove-flow-group", log.Fields{"group-id": groupID, "err": err})
Kent Hagermane6ff1012020-07-14 15:07:53 -04002549 }
Esin Karamanccb714b2019-11-29 15:02:06 +00002550 }
David K. Bainbridge794735f2020-02-11 21:01:37 -08002551
David K. Bainbridge794735f2020-02-11 21:01:37 -08002552 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002553}
2554
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002555// 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 +00002556func (f *OpenOltFlowMgr) getNNIInterfaceIDOfMulticastFlow(ctx context.Context, classifierInfo map[string]interface{}) (uint32, error) {
2557 if inPort, ok := classifierInfo[InPort]; ok {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002558 nniInterfaceID, err := plt.IntfIDFromNniPortNum(ctx, inPort.(uint32))
Esin Karaman65409d82020-03-18 10:58:18 +00002559 if err != nil {
2560 return 0, olterrors.NewErrInvalidValue(log.Fields{"nni-in-port-number": inPort}, err)
2561 }
2562 return nniInterfaceID, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002563 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002564
2565 // TODO: For now we support only one NNI port in VOLTHA. We shall use only the first NNI port, i.e., interface-id 0.
2566 return 0, nil
Esin Karamanccb714b2019-11-29 15:02:06 +00002567}
2568
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002569// sendTPDownloadMsgToChild send payload
bseeniva0b9cbcb2026-02-12 19:11:11 +05302570func (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 +00002571 onuDev, err := f.getOnuDevice(ctx, intfID, onuID)
Manikkaraj k884c1242019-04-11 16:26:42 +05302572 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002573 logger.Errorw(ctx, "couldnt-find-onu-child-device",
Shrey Baid26912972020-04-16 21:02:31 +05302574 log.Fields{
2575 "intf-id": intfID,
2576 "onu-id": onuID,
2577 "uni-id": uniID})
Mahir Gunyel0f89fd22020-04-11 18:24:42 -07002578 return err
manikkaraj kbf256be2019-03-25 00:13:48 +05302579 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002580 logger.Debugw(ctx, "got-child-device-from-olt-device-handler", log.Fields{"onu-id": onuDev.deviceID})
manikkaraj k17652a72019-05-06 09:06:36 -04002581
yasin saplibddc2d72022-02-08 13:10:17 +00002582 tpPath := f.getTPpath(ctx, uni, TpID)
khenaidoodc2116e2021-10-19 17:33:19 -04002583 tpDownloadMsg := &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04002584 DeviceId: onuDev.deviceID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002585 UniId: uniID,
2586 TpInstancePath: tpPath,
bseeniva0b9cbcb2026-02-12 19:11:11 +05302587 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002588 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05302589 logger.Debugw(ctx, "sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpDownloadMsg": tpDownloadMsg.String()})
khenaidoo106c61a2021-08-11 18:05:46 -04002590
2591 err = f.deviceHandler.sendDownloadTechProfileToChildAdapter(ctx, onuDev.adapterEndpoint, tpDownloadMsg)
2592 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302593 return olterrors.NewErrCommunication("send-techprofile-download-request",
2594 log.Fields{
khenaidoo106c61a2021-08-11 18:05:46 -04002595 "from-adapter": f.deviceHandler.openOLT.config.AdapterEndpoint,
Shrey Baid26912972020-04-16 21:02:31 +05302596 "to-adapter": onuDev.deviceType,
2597 "onu-id": onuDev.deviceID,
khenaidoo106c61a2021-08-11 18:05:46 -04002598 "proxyDeviceID": onuDev.proxyDeviceID}, err)
manikkaraj k17652a72019-05-06 09:06:36 -04002599 }
balaji.nagarajan31db4ea2026-01-28 09:13:55 +05302600 logger.Debugw(ctx, "success-sending-load-tech-profile-request-to-brcm-onu-adapter", log.Fields{"tpid": TpID})
Manikkaraj k884c1242019-04-11 16:26:42 +05302601 return nil
manikkaraj kbf256be2019-03-25 00:13:48 +05302602}
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002603
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002604// GetLogicalPortFromPacketIn function computes logical port UNI/NNI port from packet-in indication and returns the same
npujarec5762e2020-01-01 14:08:48 +05302605func (f *OpenOltFlowMgr) GetLogicalPortFromPacketIn(ctx context.Context, packetIn *openoltpb2.PacketIndication) (uint32, error) {
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002606 var logicalPortNum uint32
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002607
mgouda86543582025-10-29 20:58:16 +05302608 switch packetIn.IntfType {
2609 case "pon":
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002610 // packet indication does not have serial number , so sending as nil
Esin Karamandf392e12020-12-16 13:33:09 +00002611 // get onu and uni ids associated with the given pon and gem ports
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002612 onuID, uniID := packetIn.OnuId, packetIn.UniId
2613 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 +00002614
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002615 if packetIn.PortNo != 0 {
2616 logicalPortNum = packetIn.PortNo
2617 } else {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002618 logicalPortNum = plt.MkUniPortNum(ctx, packetIn.IntfId, onuID, uniID)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002619 }
2620 // 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 +00002621 f.UpdateGemPortForPktIn(ctx, packetIn.IntfId, onuID, logicalPortNum, packetIn.GemportId, packetIn.Pkt)
mgouda86543582025-10-29 20:58:16 +05302622 case "nni":
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002623 logicalPortNum = plt.IntfIDToPortNo(packetIn.IntfId, voltha.Port_ETHERNET_NNI)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002624 }
Girish Gowdraeb450292020-10-26 10:03:39 -07002625
2626 if logger.V(log.DebugLevel) {
2627 logger.Debugw(ctx, "retrieved-logicalport-from-packet-in",
2628 log.Fields{
2629 "logical-port-num": logicalPortNum,
2630 "intf-type": packetIn.IntfType,
2631 "packet": hex.EncodeToString(packetIn.Pkt),
2632 })
2633 }
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002634 return logicalPortNum, nil
2635}
2636
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002637// GetPacketOutGemPortID returns gemPortId
Esin Karaman7fb80c22020-07-16 14:23:33 +00002638func (f *OpenOltFlowMgr) GetPacketOutGemPortID(ctx context.Context, intfID uint32, onuID uint32, portNum uint32, packet []byte) (uint32, error) {
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002639 var gemPortID uint32
Esin Karaman7fb80c22020-07-16 14:23:33 +00002640
2641 ctag, priority, err := getCTagFromPacket(ctx, packet)
2642 if err != nil {
2643 return 0, err
2644 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302645
Esin Karaman7fb80c22020-07-16 14:23:33 +00002646 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: portNum, VlanID: ctag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002647 var ok bool
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002648 f.packetInGemPortLock.RLock()
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002649 gemPortID, ok = f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002650 f.packetInGemPortLock.RUnlock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302651 if ok {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002652 logger.Debugw(ctx, "found-gemport-for-pktin-key",
Shrey Baid26912972020-04-16 21:02:31 +05302653 log.Fields{
2654 "pktinkey": pktInkey,
2655 "gem": gemPortID})
Matteo Scandoloabf9c512020-06-23 19:31:14 -07002656
2657 return gemPortID, nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002658 }
Akash Kankanala041a2122024-10-16 15:49:22 +05302659 // 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 +00002660 gemPortID, err = f.resourceMgr.GetGemPortFromOnuPktIn(ctx, pktInkey)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302661 if err == nil {
2662 if gemPortID != 0 {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002663 f.packetInGemPortLock.Lock()
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302664 f.packetInGemPort[pktInkey] = gemPortID
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002665 f.packetInGemPortLock.Unlock()
Neha Sharma96b7bf22020-06-15 10:37:32 +00002666 logger.Infow(ctx, "found-gem-port-from-kv-store-and-updating-cache-with-gemport",
Shrey Baid26912972020-04-16 21:02:31 +05302667 log.Fields{
2668 "pktinkey": pktInkey,
2669 "gem": gemPortID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302670 return gemPortID, nil
2671 }
2672 }
Shrey Baid26912972020-04-16 21:02:31 +05302673 return uint32(0), olterrors.NewErrNotFound("gem-port",
2674 log.Fields{
2675 "pktinkey": pktInkey,
2676 "gem": gemPortID}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002677}
2678
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002679func (f *OpenOltFlowMgr) addTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
2680 logger.Debug(ctx, "adding-trap-of-nni-flow")
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002681 action := make(map[string]interface{})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002682 classifier[PacketTagType] = DoubleTag
2683 action[TrapToHost] = true
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002684 /* We manage flowId resource pool on per PON port basis.
2685 Since this situation is tricky, as a hack, we pass the NNI port
2686 index (network_intf_id) as PON port Index for the flowId resource
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002687 pool. Also, there is no ONU Id available for trapping packets
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002688 on NNI port, use onu_id as -1 (invalid)
2689 ****************** CAVEAT *******************
2690 This logic works if the NNI Port Id falls within the same valid
2691 range of PON Port Ids. If this doesn't work for some OLT Vendor
2692 we need to have a re-look at this.
2693 *********************************************
2694 */
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002695 onuID := -1
2696 uniID := -1
2697 gemPortID := -1
2698 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002699 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302700 if err != nil {
Shrey Baid26912972020-04-16 21:02:31 +05302701 return olterrors.NewErrNotFound("nni-intreface-id",
2702 log.Fields{
2703 "classifier": classifier,
2704 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002705 err)
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05302706 }
2707
yasin saplibddc2d72022-02-08 13:10:17 +00002708 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002709 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002710 logger.Info(ctx, "flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002711 return nil
yasin saplid0566272021-12-21 09:10:30 +00002712 } else if err != nil {
2713 logger.Errorw(ctx, "aborting-addTrapFlowOnNNI--flow-may-already-exist",
2714 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2715 return err
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002716 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002717
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002718 logger.Debugw(ctx, "creating-trap-of-nni-flow",
2719 log.Fields{
2720 "classifier": classifier,
2721 "action": action,
2722 "flowId": logicalFlow.Id,
2723 "intf-id": networkInterfaceID})
2724
David K. Bainbridge794735f2020-02-11 21:01:37 -08002725 classifierProto, err := makeOpenOltClassifierField(classifier)
2726 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002727 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002728 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05302729 logger.Debugw(ctx, "created-classifier-proto", log.Fields{"classifier": classifierProto.String()})
Gamze Abaka724d0852020-03-18 12:10:24 +00002730 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002731 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002732 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002733 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05302734 logger.Debugw(ctx, "created-action-proto", log.Fields{"action": actionProto.String()})
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002735 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2736 OnuId: int32(onuID), // OnuId not required
2737 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002738 FlowId: logicalFlow.Id,
David K. Bainbridge82efc492019-09-04 09:57:11 -07002739 FlowType: Downstream,
Girish Gowdru6a80bbd2019-07-02 07:36:09 -07002740 AllocId: int32(allocID), // AllocId not used
2741 NetworkIntfId: int32(networkInterfaceID),
2742 GemportId: int32(gemPortID), // GemportId not used
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002743 Classifier: classifierProto,
2744 Action: actionProto,
2745 Priority: int32(logicalFlow.Priority),
2746 Cookie: logicalFlow.Cookie,
2747 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002748 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05302749 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow-id": downstreamflow.FlowId}, err)
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002750 }
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002751 logger.Info(ctx, "trap-on-nni-flow-added–to-device-successfully")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002752 return nil
manikkaraj k9eb6cac2019-05-09 12:32:03 -04002753}
salmansiddiqui7ac62132019-08-22 03:58:50 +00002754
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002755// getPacketTypeFromClassifiers finds and returns packet type of a flow by checking flow classifiers
Esin Karamanae41e2b2019-12-17 18:13:13 +00002756func getPacketTypeFromClassifiers(classifierInfo map[string]interface{}) string {
2757 var packetType string
2758 ovid, ivid := false, false
2759 if vlanID, ok := classifierInfo[VlanVid].(uint32); ok {
2760 vid := vlanID & VlanvIDMask
2761 if vid != ReservedVlan {
2762 ovid = true
2763 }
2764 }
Girish Gowdrab23f1de2022-03-24 12:01:17 -07002765
2766 // The classifierInfo[Metadata] is set for the following flows
2767 // - In the Downstream datapath flow table0 and table1. From the OLT perspective, only table0 downstream flow is relevant.
2768 // - Mcast flow that points to a group in the action/treatment
2769 // This value, when present and valid (not 0 and not 4096), is interpreted as below
2770 // - inner vid for a double tagged packet in the datapath flow
2771 // - outer vid for a single tagged packet in the datapath flow
2772 // - inner vid in the mcast flow that points to a group
2773
2774 // It is to be noted though that for DT FTTH downstream table0 flow, the classifierInfo[Metadata] is absent.
2775 // And consequently the ivid is not set to true. This will result in packetType being set to singleTag which is not true
2776 // Interestingly enough, this function `getPacketTypeFromClassifiers` is called only by Mcast flow handlers and
2777 // 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 +00002778 if metadata, ok := classifierInfo[Metadata].(uint64); ok {
2779 vid := uint32(metadata)
2780 if vid != ReservedVlan {
2781 ivid = true
2782 }
2783 }
2784 if ovid && ivid {
2785 packetType = DoubleTag
2786 } else if !ovid && !ivid {
2787 packetType = Untagged
2788 } else {
2789 packetType = SingleTag
2790 }
2791 return packetType
2792}
2793
Joey Armstrong3f0e2422023-07-05 18:25:41 -04002794// addIgmpTrapFlowOnNNI adds a trap-to-host flow on NNI
David K. Bainbridge794735f2020-02-11 21:01:37 -08002795func (f *OpenOltFlowMgr) addIgmpTrapFlowOnNNI(ctx context.Context, logicalFlow *ofp.OfpFlowStats, classifier map[string]interface{}, portNo uint32) error {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002796 logger.Infow(ctx, "adding-igmp-trap-of-nni-flow", log.Fields{"classifier-info": classifier})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002797 action := make(map[string]interface{})
2798 classifier[PacketTagType] = getPacketTypeFromClassifiers(classifier)
2799 action[TrapToHost] = true
2800 /* We manage flowId resource pool on per PON port basis.
2801 Since this situation is tricky, as a hack, we pass the NNI port
2802 index (network_intf_id) as PON port Index for the flowId resource
2803 pool. Also, there is no ONU Id available for trapping packets
2804 on NNI port, use onu_id as -1 (invalid)
2805 ****************** CAVEAT *******************
2806 This logic works if the NNI Port Id falls within the same valid
2807 range of PON Port Ids. If this doesn't work for some OLT Vendor
2808 we need to have a re-look at this.
2809 *********************************************
2810 */
2811 onuID := -1
2812 uniID := -1
2813 gemPortID := -1
2814 allocID := -1
Neha Sharma96b7bf22020-06-15 10:37:32 +00002815 networkInterfaceID, err := getNniIntfID(ctx, classifier, action)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002816 if err != nil {
Thomas Lee S94109f12020-03-03 16:39:29 +05302817 return olterrors.NewErrNotFound("nni-interface-id", log.Fields{
David K. Bainbridge794735f2020-02-11 21:01:37 -08002818 "classifier": classifier,
2819 "action": action},
Girish Kumarf26e4882020-03-05 06:49:10 +00002820 err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002821 }
yasin saplibddc2d72022-02-08 13:10:17 +00002822 present, err := f.resourceMgr.IsFlowOnKvStore(ctx, int32(onuID), logicalFlow.Id)
yasin saplid0566272021-12-21 09:10:30 +00002823 if present {
Neha Sharma96b7bf22020-06-15 10:37:32 +00002824 logger.Info(ctx, "igmp-flow-exists-not-re-adding")
David K. Bainbridge794735f2020-02-11 21:01:37 -08002825 return nil
yasin saplid0566272021-12-21 09:10:30 +00002826 } else if err != nil {
2827 logger.Errorw(ctx, "aborting-addIgmpTrapFlowOnNNI--flow-may-already-exist",
2828 log.Fields{"intf-id": networkInterfaceID, "onu-id": onuID, "flow-id": logicalFlow.Id})
2829 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002830 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002831
David K. Bainbridge794735f2020-02-11 21:01:37 -08002832 classifierProto, err := makeOpenOltClassifierField(classifier)
2833 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002834 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifier}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002835 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05302836 logger.Debugw(ctx, "created-classifier-proto-for-the-igmp-flow", log.Fields{"classifier": classifierProto.String()})
Gamze Abaka724d0852020-03-18 12:10:24 +00002837 actionProto, err := makeOpenOltActionField(action, classifier)
David K. Bainbridge794735f2020-02-11 21:01:37 -08002838 if err != nil {
Girish Kumarf26e4882020-03-05 06:49:10 +00002839 return olterrors.NewErrInvalidValue(log.Fields{"action": action}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002840 }
bseeniva0b9cbcb2026-02-12 19:11:11 +05302841 logger.Debugw(ctx, "created-action-proto-for-the-igmp-flow", log.Fields{"action": actionProto.String()})
Esin Karamanae41e2b2019-12-17 18:13:13 +00002842 downstreamflow := openoltpb2.Flow{AccessIntfId: int32(-1), // AccessIntfId not required
2843 OnuId: int32(onuID), // OnuId not required
2844 UniId: int32(uniID), // UniId not used
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002845 FlowId: logicalFlow.Id,
Esin Karamanae41e2b2019-12-17 18:13:13 +00002846 FlowType: Downstream,
2847 AllocId: int32(allocID), // AllocId not used
2848 NetworkIntfId: int32(networkInterfaceID),
2849 GemportId: int32(gemPortID), // GemportId not used
2850 Classifier: classifierProto,
2851 Action: actionProto,
2852 Priority: int32(logicalFlow.Priority),
2853 Cookie: logicalFlow.Cookie,
2854 PortNo: portNo}
David K. Bainbridge794735f2020-02-11 21:01:37 -08002855 if err := f.addFlowToDevice(ctx, logicalFlow, &downstreamflow); err != nil {
bseeniva0b9cbcb2026-02-12 19:11:11 +05302856 return olterrors.NewErrFlowOp("add", logicalFlow.Id, log.Fields{"flow-id": downstreamflow.FlowId}, err)
Esin Karamanae41e2b2019-12-17 18:13:13 +00002857 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00002858 logger.Info(ctx, "igmp-trap-on-nni-flow-added-to-device-successfully")
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002859
David K. Bainbridge794735f2020-02-11 21:01:37 -08002860 return nil
Esin Karamanae41e2b2019-12-17 18:13:13 +00002861}
2862
salmansiddiqui7ac62132019-08-22 03:58:50 +00002863func verifyMeterIDAndGetDirection(MeterID uint32, Dir tp_pb.Direction) (string, error) {
2864 if MeterID == 0 { // This should never happen
Thomas Lee S94109f12020-03-03 16:39:29 +05302865 return "", olterrors.NewErrInvalidValue(log.Fields{"meter-id": MeterID}, nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00002866 }
mgouda86543582025-10-29 20:58:16 +05302867 switch Dir {
2868 case tp_pb.Direction_UPSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002869 return "upstream", nil
mgouda86543582025-10-29 20:58:16 +05302870 case tp_pb.Direction_DOWNSTREAM:
salmansiddiqui7ac62132019-08-22 03:58:50 +00002871 return "downstream", nil
2872 }
2873 return "", nil
2874}
2875
Kent Hagermane6ff1012020-07-14 15:07:53 -04002876// nolint: gocyclo
npujarec5762e2020-01-01 14:08:48 +05302877func (f *OpenOltFlowMgr) checkAndAddFlow(ctx context.Context, args map[string]uint32, classifierInfo map[string]interface{},
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002878 actionInfo map[string]interface{}, flow *ofp.OfpFlowStats, TpInst interface{}, gemPorts []uint32,
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002879 tpID uint32, uni string) error {
Gamze Abaka7650be62021-02-26 10:50:36 +00002880 var gemPortID uint32
Gamze Abakafee36392019-10-03 11:17:24 +00002881 intfID := args[IntfID]
2882 onuID := args[OnuID]
2883 uniID := args[UniID]
2884 portNo := args[PortNo]
Takahiro Suzuki2ba0e0b2020-06-05 14:23:03 -07002885 allocID := args[AllocID]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002886 pbitToGem := make(map[uint32]uint32)
Gamze Abaka7650be62021-02-26 10:50:36 +00002887 gemToAes := make(map[uint32]bool)
2888
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002889 var attributes []*tp_pb.GemPortAttributes
Gamze Abaka7650be62021-02-26 10:50:36 +00002890 var direction = tp_pb.Direction_UPSTREAM
2891 switch TpInst := TpInst.(type) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002892 case *tp_pb.TechProfileInstance:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07002893 if plt.IsUpstream(actionInfo[Output].(uint32)) {
Gamze Abaka7650be62021-02-26 10:50:36 +00002894 attributes = TpInst.UpstreamGemPortAttributeList
2895 } else {
2896 attributes = TpInst.DownstreamGemPortAttributeList
2897 direction = tp_pb.Direction_DOWNSTREAM
2898 }
2899 default:
2900 logger.Errorw(ctx, "unsupported-tech", log.Fields{"tpInst": TpInst})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002901 return olterrors.NewErrInvalidValue(log.Fields{"tpInst": TpInst}, nil)
Gamze Abaka7650be62021-02-26 10:50:36 +00002902 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002903
2904 if len(gemPorts) == 1 {
2905 // If there is only single gemport use that and do not populate pbitToGem map
Gamze Abaka7650be62021-02-26 10:50:36 +00002906 gemPortID = gemPorts[0]
2907 gemToAes[gemPortID], _ = strconv.ParseBool(attributes[0].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002908 } else if pcp, ok := classifierInfo[VlanPcp]; !ok {
2909 for idx, gemID := range gemPorts {
Gamze Abaka7650be62021-02-26 10:50:36 +00002910 pBitMap := attributes[idx].PbitMap
2911 // Trim the bitMapPrefix form the binary string and then iterate each character in the binary string.
2912 // If the character is set to pbit1, extract the pcp value from the position of this character in the string.
2913 // Update the pbitToGem map with key being the pcp bit and the value being the gemPortID that consumes
khenaidoodc2116e2021-10-19 17:33:19 -04002914 // this pcp bit traffca.
Gamze Abaka7650be62021-02-26 10:50:36 +00002915 for pos, pbitSet := range strings.TrimPrefix(pBitMap, bitMapPrefix) {
2916 if pbitSet == pbit1 {
2917 pcp := uint32(len(strings.TrimPrefix(pBitMap, bitMapPrefix))) - 1 - uint32(pos)
2918 pbitToGem[pcp] = gemID
2919 gemToAes[gemID], _ = strconv.ParseBool(attributes[idx].AesEncryption)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002920 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002921 }
2922 }
2923 } else { // Extract the exact gemport which maps to the PCP classifier in the flow
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07002924 if gem := f.techprofile.GetGemportForPbit(ctx, TpInst, direction, pcp.(uint32)); gem != nil {
2925 gemPortID = gem.(*tp_pb.GemPortAttributes).GemportId
2926 gemToAes[gemPortID], _ = strconv.ParseBool(gem.(*tp_pb.GemPortAttributes).AesEncryption)
Gamze Abaka7650be62021-02-26 10:50:36 +00002927 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002928 }
2929
Akash Kankanala041a2122024-10-16 15:49:22 +05302930 flowContext := &flowContext{classifierInfo, actionInfo, flow, pbitToGem, gemToAes, intfID, onuID, uniID, portNo, allocID, gemPortID, tpID}
Gamze Abaka7650be62021-02-26 10:50:36 +00002931
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302932 var nni_port uint32
2933 if plt.IsUpstream(actionInfo[Output].(uint32)) {
2934 if !plt.IsControllerBoundFlow(actionInfo[Output].(uint32)) {
2935 nni_port = actionInfo[Output].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2936 }
2937 } else {
2938 nni_port = classifierInfo[InPort].(uint32) & 0x1f // convert e.g. 16777220 to port 4 (starting with 0)
2939 }
2940
salmansiddiqui7ac62132019-08-22 03:58:50 +00002941 if ipProto, ok := classifierInfo[IPProto]; ok {
mgouda86543582025-10-29 20:58:16 +05302942 switch ipProto.(uint32) {
2943 case IPProtoDhcp:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002944 logger.Infow(ctx, "adding-dhcp-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002945 "tp-id": tpID,
2946 "alloc-id": allocID,
2947 "intf-id": intfID,
2948 "onu-id": onuID,
2949 "uni-id": uniID,
2950 })
Akash Kankanala041a2122024-10-16 15:49:22 +05302951 // Adding DHCP upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00002952 if err := f.addDHCPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002953 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002954 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05302955 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002956 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00002957 }
mgouda86543582025-10-29 20:58:16 +05302958 case IgmpProto:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002959 logger.Infow(ctx, "adding-us-igmp-flow",
Shrey Baid26912972020-04-16 21:02:31 +05302960 log.Fields{
2961 "intf-id": intfID,
2962 "onu-id": onuID,
2963 "uni-id": uniID,
2964 "classifier-info:": classifierInfo})
Gamze Abaka7650be62021-02-26 10:50:36 +00002965 if err := f.addIGMPTrapFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002966 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00002967 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 +05302968 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002969 return err
Esin Karamanae41e2b2019-12-17 18:13:13 +00002970 }
mgouda86543582025-10-29 20:58:16 +05302971 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00002972 logger.Errorw(ctx, "invalid-classifier-to-handle", log.Fields{"classifier": classifierInfo, "action": actionInfo})
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00002973 return olterrors.NewErrInvalidValue(log.Fields{"classifier": classifierInfo, "action": actionInfo}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00002974 }
2975 } else if ethType, ok := classifierInfo[EthType]; ok {
mgouda86543582025-10-29 20:58:16 +05302976 switch ethType.(uint32) {
2977 case EapEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002978 logger.Infow(ctx, "adding-eapol-flow", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07002979 "intf-id": intfID,
2980 "onu-id": onuID,
2981 "uni-id": uniID,
Marcos Aurelio Carrero (Furukawa)388fb0a2021-02-04 18:05:11 -03002982 "ethType": ethType,
Matteo Scandolo92186242020-06-12 10:54:18 -07002983 })
salmansiddiqui7ac62132019-08-22 03:58:50 +00002984 var vlanID uint32
2985 if val, ok := classifierInfo[VlanVid]; ok {
2986 vlanID = (val.(uint32)) & VlanvIDMask
2987 } else {
2988 vlanID = DefaultMgmtVlan
2989 }
Gamze Abaka7650be62021-02-26 10:50:36 +00002990 if err := f.addEthTypeBasedFlow(ctx, flowContext, vlanID, ethType.(uint32)); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07002991 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
salmansiddiqui7ac62132019-08-22 03:58:50 +00002995 }
mgouda86543582025-10-29 20:58:16 +05302996 case PPPoEDEthType:
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03002997 logger.Infow(ctx, "adding-pppoed-flow", log.Fields{
2998 "tp-id": tpID,
2999 "alloc-id": allocID,
3000 "intf-id": intfID,
3001 "onu-id": onuID,
3002 "uni-id": uniID,
3003 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303004 // Adding PPPOED upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003005 if err := f.addUpstreamTrapFlow(ctx, flowContext); err != nil {
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003006 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003007 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 +05303008 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003009 return err
Marcos Aurelio Carrero (Furukawa)1dc2bfb2021-02-17 15:10:12 -03003010 }
salmansiddiqui7ac62132019-08-22 03:58:50 +00003011 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003012 } else if direction == tp_pb.Direction_UPSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003013 logger.Infow(ctx, "adding-upstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003014 "intf-id": intfID,
3015 "onu-id": onuID,
3016 "uni-id": uniID,
3017 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303018 // Adding HSIA upstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003019 if err := f.addUpstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003020 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003021 logger.Errorw(ctx, "reverting-scheduler-and-queue-for-onu", log.Fields{"intf-id": intfID, "onu-id": onuID, "uni-id": uniID, "flow-id": flow.Id, "tp-id": tpID})
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303022 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003023 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003024 }
Gamze Abaka7650be62021-02-26 10:50:36 +00003025 } else if direction == tp_pb.Direction_DOWNSTREAM {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003026 logger.Infow(ctx, "adding-downstream-data-rule", log.Fields{
Matteo Scandolo92186242020-06-12 10:54:18 -07003027 "intf-id": intfID,
3028 "onu-id": onuID,
3029 "uni-id": uniID,
3030 })
Akash Kankanala041a2122024-10-16 15:49:22 +05303031 // Adding HSIA downstream flow
Gamze Abaka7650be62021-02-26 10:50:36 +00003032 if err := f.addDownstreamDataPathFlow(ctx, flowContext); err != nil {
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003033 logger.Warn(ctx, err)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003034 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 +05303035 _ = f.clearResources(ctx, intfID, int32(onuID), int32(uniID), flow.Id, portNo, tpID, false, nni_port)
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003036 return err
salmansiddiqui7ac62132019-08-22 03:58:50 +00003037 }
3038 } else {
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003039 return olterrors.NewErrInvalidValue(log.Fields{
3040 "intf-id": intfID,
3041 "onu-id": onuID,
3042 "uni-id": uniID,
3043 "classifier": classifierInfo,
3044 "action": actionInfo,
3045 "flow": flow},
3046 nil).Log()
salmansiddiqui7ac62132019-08-22 03:58:50 +00003047 }
3048 // Send Techprofile download event to child device in go routine as it takes time
Kent Hagermane6ff1012020-07-14 15:07:53 -04003049 go func() {
bseeniva0b9cbcb2026-02-12 19:11:11 +05303050 if err := f.sendTPDownloadMsgToChild(ctx, intfID, onuID, uniID, uni, tpID, TpInst.(*tp_pb.TechProfileInstance)); err != nil {
Kent Hagermane6ff1012020-07-14 15:07:53 -04003051 logger.Warn(ctx, err)
3052 }
3053 }()
Gamze Abaka6d0a64f2021-11-18 08:08:33 +00003054 return nil
salmansiddiqui7ac62132019-08-22 03:58:50 +00003055}
3056
Gamze Abakacb0e6772021-06-10 08:32:12 +00003057func (f *OpenOltFlowMgr) isAllocUsedByAnotherUNI(ctx context.Context, sq schedQueue) bool {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003058 tpInst := sq.tpInst.(*tp_pb.TechProfileInstance)
3059 if tpInst.InstanceControl.Onu == "single-instance" && sq.direction == tp_pb.Direction_UPSTREAM {
3060 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 +05303061 for i := 0; i < len(tpInstances); i++ {
bseeniva0b9cbcb2026-02-12 19:11:11 +05303062 tpI := &tpInstances[i]
Gamze Abakacb0e6772021-06-10 08:32:12 +00003063 if tpI.SubscriberIdentifier != tpInst.SubscriberIdentifier &&
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003064 tpI.UsScheduler.AllocId == tpInst.UsScheduler.AllocId {
Girish Gowdraf3728b12022-02-02 21:46:51 -08003065 logger.Debugw(ctx, "alloc-is-in-use-on-another-uni",
Gamze Abakacb0e6772021-06-10 08:32:12 +00003066 log.Fields{
3067 "device-id": f.deviceHandler.device.Id,
3068 "intfID": sq.intfID,
3069 "onuID": sq.onuID,
3070 "uniID": sq.uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003071 "allocID": tpI.UsScheduler.AllocId,
Gamze Abakacb0e6772021-06-10 08:32:12 +00003072 })
3073 return true
Girish Gowdra54934262019-11-13 14:19:55 +05303074 }
3075 }
3076 }
Gamze Abakacb0e6772021-06-10 08:32:12 +00003077 return false
Gamze Abakafee36392019-10-03 11:17:24 +00003078}
3079
Neha Sharma96b7bf22020-06-15 10:37:32 +00003080func formulateClassifierInfoFromFlow(ctx context.Context, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) {
Scott Baker355d1742019-10-24 10:57:52 -07003081 for _, field := range flows.GetOfbFields(flow) {
mgouda86543582025-10-29 20:58:16 +05303082 switch field.Type {
3083 case flows.ETH_TYPE:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003084 classifierInfo[EthType] = field.GetEthType()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003085 logger.Debug(ctx, "field-type-eth-type", log.Fields{"classifierInfo[ETH_TYPE]": classifierInfo[EthType].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303086 case flows.ETH_DST:
Esin Karamanccb714b2019-11-29 15:02:06 +00003087 classifierInfo[EthDst] = field.GetEthDst()
Girish Gowdraffa52e52022-02-16 15:48:10 -08003088 logger.Debug(ctx, "field-type-eth-dst", log.Fields{"classifierInfo[ETH_DST]": classifierInfo[EthDst].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303089 case flows.ETH_SRC:
Girish Gowdraffa52e52022-02-16 15:48:10 -08003090 classifierInfo[EthSrc] = field.GetEthSrc()
3091 logger.Debug(ctx, "field-type-eth-src", log.Fields{"classifierInfo[ETH_SRC]": classifierInfo[EthSrc].([]uint8)})
mgouda86543582025-10-29 20:58:16 +05303092 case flows.IP_PROTO:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003093 classifierInfo[IPProto] = field.GetIpProto()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003094 logger.Debug(ctx, "field-type-ip-proto", log.Fields{"classifierInfo[IP_PROTO]": classifierInfo[IPProto].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303095 case flows.IN_PORT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003096 classifierInfo[InPort] = field.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003097 logger.Debug(ctx, "field-type-in-port", log.Fields{"classifierInfo[IN_PORT]": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303098 case flows.VLAN_VID:
Andrea Campanellafaa42152021-10-28 11:50:56 +05303099 // The ReservedVlan is used to signify transparent vlan. Do not do any classification when we see ReservedVlan
3100 if field.GetVlanVid() != ReservedVlan {
3101 classifierInfo[VlanVid] = field.GetVlanVid() & 0xfff
3102 logger.Debug(ctx, "field-type-vlan-vid", log.Fields{"classifierInfo[VLAN_VID]": classifierInfo[VlanVid].(uint32)})
3103 }
mgouda86543582025-10-29 20:58:16 +05303104 case flows.VLAN_PCP:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003105 classifierInfo[VlanPcp] = field.GetVlanPcp()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003106 logger.Debug(ctx, "field-type-vlan-pcp", log.Fields{"classifierInfo[VLAN_PCP]": classifierInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303107 case flows.UDP_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003108 classifierInfo[UDPDst] = field.GetUdpDst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003109 logger.Debug(ctx, "field-type-udp-dst", log.Fields{"classifierInfo[UDP_DST]": classifierInfo[UDPDst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303110 case flows.UDP_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003111 classifierInfo[UDPSrc] = field.GetUdpSrc()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003112 logger.Debug(ctx, "field-type-udp-src", log.Fields{"classifierInfo[UDP_SRC]": classifierInfo[UDPSrc].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303113 case flows.IPV4_DST:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003114 classifierInfo[Ipv4Dst] = field.GetIpv4Dst()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003115 logger.Debug(ctx, "field-type-ipv4-dst", log.Fields{"classifierInfo[IPV4_DST]": classifierInfo[Ipv4Dst].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303116 case flows.IPV4_SRC:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003117 classifierInfo[Ipv4Src] = field.GetIpv4Src()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003118 logger.Debug(ctx, "field-type-ipv4-src", log.Fields{"classifierInfo[IPV4_SRC]": classifierInfo[Ipv4Src].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303119 case flows.METADATA:
David K. Bainbridge82efc492019-09-04 09:57:11 -07003120 classifierInfo[Metadata] = field.GetTableMetadata()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003121 logger.Debug(ctx, "field-type-metadata", log.Fields{"classifierInfo[Metadata]": classifierInfo[Metadata].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303122 case flows.TUNNEL_ID:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003123 classifierInfo[TunnelID] = field.GetTunnelId()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003124 logger.Debug(ctx, "field-type-tunnelId", log.Fields{"classifierInfo[TUNNEL_ID]": classifierInfo[TunnelID].(uint64)})
mgouda86543582025-10-29 20:58:16 +05303125 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003126 logger.Errorw(ctx, "un-supported-field-type", log.Fields{"type": field.Type})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003127 return
3128 }
3129 }
3130}
3131
Neha Sharma96b7bf22020-06-15 10:37:32 +00003132func formulateActionInfoFromFlow(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Scott Baker355d1742019-10-24 10:57:52 -07003133 for _, action := range flows.GetActions(flow) {
mgouda86543582025-10-29 20:58:16 +05303134 switch action.Type {
3135 case flows.OUTPUT:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003136 if out := action.GetOutput(); out != nil {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003137 actionInfo[Output] = out.GetPort()
Neha Sharma96b7bf22020-06-15 10:37:32 +00003138 logger.Debugw(ctx, "action-type-output", log.Fields{"out-port": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003139 } else {
Girish Kumarf26e4882020-03-05 06:49:10 +00003140 return olterrors.NewErrInvalidValue(log.Fields{"output-port": nil}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003141 }
mgouda86543582025-10-29 20:58:16 +05303142 case flows.POP_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003143 actionInfo[PopVlan] = true
Neha Sharma96b7bf22020-06-15 10:37:32 +00003144 logger.Debugw(ctx, "action-type-pop-vlan", log.Fields{"in_port": classifierInfo[InPort].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303145 case flows.PUSH_VLAN:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003146 if out := action.GetPush(); out != nil {
3147 if tpid := out.GetEthertype(); tpid != 0x8100 {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003148 logger.Errorw(ctx, "invalid ethertype in push action", log.Fields{"ethertype": actionInfo[PushVlan].(int32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003149 } else {
3150 actionInfo[PushVlan] = true
3151 actionInfo[TPID] = tpid
Neha Sharma96b7bf22020-06-15 10:37:32 +00003152 logger.Debugw(ctx, "action-type-push-vlan",
Shrey Baid26912972020-04-16 21:02:31 +05303153 log.Fields{
3154 "push-tpid": actionInfo[TPID].(uint32),
3155 "in-port": classifierInfo[InPort].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003156 }
3157 }
mgouda86543582025-10-29 20:58:16 +05303158 case flows.SET_FIELD:
salmansiddiqui7ac62132019-08-22 03:58:50 +00003159 if out := action.GetSetField(); out != nil {
3160 if field := out.GetField(); field != nil {
3161 if ofClass := field.GetOxmClass(); ofClass != ofp.OfpOxmClass_OFPXMC_OPENFLOW_BASIC {
Girish Kumarf26e4882020-03-05 06:49:10 +00003162 return olterrors.NewErrInvalidValue(log.Fields{"openflow-class": ofClass}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003163 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003164 /*logger.Debugw(ctx, "action-type-set-field",log.Fields{"field": field, "in_port": classifierInfo[IN_PORT].(uint32)})*/
3165 formulateSetFieldActionInfoFromFlow(ctx, field, actionInfo)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003166 }
3167 }
mgouda86543582025-10-29 20:58:16 +05303168 case flows.GROUP:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003169 formulateGroupActionInfoFromFlow(ctx, action, actionInfo)
mgouda86543582025-10-29 20:58:16 +05303170 default:
Girish Kumarf26e4882020-03-05 06:49:10 +00003171 return olterrors.NewErrInvalidValue(log.Fields{"action-type": action.Type}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003172 }
3173 }
3174 return nil
3175}
3176
Neha Sharma96b7bf22020-06-15 10:37:32 +00003177func formulateSetFieldActionInfoFromFlow(ctx context.Context, field *ofp.OfpOxmField, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003178 if ofbField := field.GetOfbField(); ofbField != nil {
Gamze Abakac43a66e2020-05-11 11:00:42 +00003179 fieldtype := ofbField.GetType()
mgouda86543582025-10-29 20:58:16 +05303180 switch fieldtype {
3181 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_VID:
Esin Karamanccb714b2019-11-29 15:02:06 +00003182 if vlan := ofbField.GetVlanVid(); vlan != 0 {
3183 actionInfo[VlanVid] = vlan & 0xfff
Neha Sharma96b7bf22020-06-15 10:37:32 +00003184 logger.Debugw(ctx, "action-set-vlan-vid", log.Fields{"actionInfo[VLAN_VID]": actionInfo[VlanVid].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003185 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003186 logger.Error(ctx, "no-invalid-vlan-id-in-set-vlan-vid-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003187 }
mgouda86543582025-10-29 20:58:16 +05303188 case ofp.OxmOfbFieldTypes_OFPXMT_OFB_VLAN_PCP:
Gamze Abakac43a66e2020-05-11 11:00:42 +00003189 pcp := ofbField.GetVlanPcp()
3190 actionInfo[VlanPcp] = pcp
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003191 logger.Debugw(ctx, "action-set-vlan-pcp", log.Fields{"actionInfo[VLAN_PCP]": actionInfo[VlanPcp].(uint32)})
mgouda86543582025-10-29 20:58:16 +05303192 default:
Neha Sharma96b7bf22020-06-15 10:37:32 +00003193 logger.Errorw(ctx, "unsupported-action-set-field-type", log.Fields{"type": fieldtype})
Esin Karamanccb714b2019-11-29 15:02:06 +00003194 }
3195 }
3196}
3197
Neha Sharma96b7bf22020-06-15 10:37:32 +00003198func formulateGroupActionInfoFromFlow(ctx context.Context, action *ofp.OfpAction, actionInfo map[string]interface{}) {
Esin Karamanccb714b2019-11-29 15:02:06 +00003199 if action.GetGroup() == nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003200 logger.Warn(ctx, "no-group-entry-found-in-the-group-action")
Esin Karamanccb714b2019-11-29 15:02:06 +00003201 } else {
3202 actionInfo[GroupID] = action.GetGroup().GroupId
Neha Sharma96b7bf22020-06-15 10:37:32 +00003203 logger.Debugw(ctx, "action-group-id", log.Fields{"actionInfo[GroupID]": actionInfo[GroupID].(uint32)})
Esin Karamanccb714b2019-11-29 15:02:06 +00003204 }
3205}
3206
Neha Sharma96b7bf22020-06-15 10:37:32 +00003207func formulateControllerBoundTrapFlowInfo(ctx context.Context, actionInfo, classifierInfo map[string]interface{}, flow *ofp.OfpFlowStats) error {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003208 if isControllerFlow := plt.IsControllerBoundFlow(actionInfo[Output].(uint32)); isControllerFlow {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003209 logger.Debug(ctx, "controller-bound-trap-flows--getting-inport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003210 /* Get UNI port/ IN Port from tunnel ID field for upstream controller bound flows */
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003211 if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003212 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003213 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003214 logger.Debugw(ctx, "upstream-pon-to-controller-flow--inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303215 log.Fields{
3216 "newinport": classifierInfo[InPort].(uint32),
3217 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003218 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303219 return olterrors.NewErrNotFound("child-in-port",
3220 log.Fields{
3221 "reason": "upstream-pon-to-controller-flow--no-inport-in-tunnelid",
3222 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003223 }
3224 }
3225 } else {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003226 logger.Debug(ctx, "non-controller-flows--getting-uniport-from-tunnelid")
salmansiddiqui7ac62132019-08-22 03:58:50 +00003227 // Downstream flow from NNI to PON port , Use tunnel ID as new OUT port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003228 if portType := plt.IntfIDToPortTypeName(actionInfo[Output].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003229 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
David K. Bainbridge82efc492019-09-04 09:57:11 -07003230 actionInfo[Output] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003231 logger.Debugw(ctx, "downstream-nni-to-pon-port-flow, outport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303232 log.Fields{
3233 "newoutport": actionInfo[Output].(uint32),
3234 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003235 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303236 return olterrors.NewErrNotFound("out-port",
3237 log.Fields{
3238 "reason": "downstream-nni-to-pon-port-flow--no-outport-in-tunnelid",
3239 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003240 }
3241 // Upstream flow from PON to NNI port , Use tunnel ID as new IN port / UNI port
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003242 } else if portType := plt.IntfIDToPortTypeName(classifierInfo[InPort].(uint32)); portType == voltha.Port_PON_OLT {
Scott Baker355d1742019-10-24 10:57:52 -07003243 if uniPort := flows.GetChildPortFromTunnelId(flow); uniPort != 0 {
salmansiddiqui7ac62132019-08-22 03:58:50 +00003244 classifierInfo[InPort] = uniPort
Neha Sharma96b7bf22020-06-15 10:37:32 +00003245 logger.Debugw(ctx, "upstream-pon-to-nni-port-flow, inport-in-tunnelid",
Shrey Baid26912972020-04-16 21:02:31 +05303246 log.Fields{
3247 "newinport": actionInfo[Output].(uint32),
3248 "outport": actionInfo[Output].(uint32)})
salmansiddiqui7ac62132019-08-22 03:58:50 +00003249 } else {
Shrey Baid26912972020-04-16 21:02:31 +05303250 return olterrors.NewErrNotFound("nni-port",
3251 log.Fields{
3252 "reason": "upstream-pon-to-nni-port-flow--no-inport-in-tunnelid",
3253 "in-port": classifierInfo[InPort].(uint32),
3254 "out-port": actionInfo[Output].(uint32),
3255 "flow": flow}, nil)
salmansiddiqui7ac62132019-08-22 03:58:50 +00003256 }
3257 }
3258 }
3259 return nil
3260}
Gamze Abakafee36392019-10-03 11:17:24 +00003261
Neha Sharma96b7bf22020-06-15 10:37:32 +00003262func getTpIDFromFlow(ctx context.Context, flow *ofp.OfpFlowStats) (uint32, error) {
Gamze Abakafee36392019-10-03 11:17:24 +00003263 /* Metadata 8 bytes:
3264 Most Significant 2 Bytes = Inner VLAN
3265 Next 2 Bytes = Tech Profile ID(TPID)
3266 Least Significant 4 Bytes = Port ID
3267 Flow Metadata carries Tech-Profile (TP) ID and is mandatory in all
3268 subscriber related flows.
3269 */
Neha Sharma96b7bf22020-06-15 10:37:32 +00003270 metadata := flows.GetMetadataFromWriteMetadataAction(ctx, flow)
Gamze Abakafee36392019-10-03 11:17:24 +00003271 if metadata == 0 {
Girish Kumarf26e4882020-03-05 06:49:10 +00003272 return 0, olterrors.NewErrNotFound("metadata", log.Fields{"flow": flow}, nil)
Gamze Abakafee36392019-10-03 11:17:24 +00003273 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003274 TpID := flows.GetTechProfileIDFromWriteMetaData(ctx, metadata)
Chaitrashree G S90a17952019-11-14 21:51:21 -05003275 return uint32(TpID), nil
Gamze Abakafee36392019-10-03 11:17:24 +00003276}
3277
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003278func appendUnique32bit(slice []uint32, item uint32) []uint32 {
Gamze Abakafee36392019-10-03 11:17:24 +00003279 for _, sliceElement := range slice {
3280 if sliceElement == item {
3281 return slice
3282 }
3283 }
3284 return append(slice, item)
3285}
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303286
yasin saplie87d4bd2021-12-06 09:04:03 +00003287func appendUnique64bit(slice []uint64, item uint64) []uint64 {
3288 for _, sliceElement := range slice {
3289 if sliceElement == item {
3290 return slice
3291 }
3292 }
3293 return append(slice, item)
3294}
3295
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303296// getNniIntfID gets nni intf id from the flow classifier/action
Neha Sharma96b7bf22020-06-15 10:37:32 +00003297func getNniIntfID(ctx context.Context, classifier map[string]interface{}, action map[string]interface{}) (uint32, error) {
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003298 portType := plt.IntfIDToPortTypeName(classifier[InPort].(uint32))
mgouda86543582025-10-29 20:58:16 +05303299 switch portType {
3300 case voltha.Port_PON_OLT:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003301 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003302 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003303 logger.Debugw(ctx, "invalid-action-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003304 log.Fields{
3305 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003306 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003307 return uint32(0), err
3308 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003309 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303310 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303311 case voltha.Port_ETHERNET_NNI:
Mahir Gunyel85f61c12021-10-06 11:53:45 -07003312 intfID, err := plt.IntfIDFromNniPortNum(ctx, classifier[InPort].(uint32))
David K. Bainbridge794735f2020-02-11 21:01:37 -08003313 if err != nil {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003314 logger.Debugw(ctx, "invalid-classifier-port-number",
David K. Bainbridge794735f2020-02-11 21:01:37 -08003315 log.Fields{
3316 "port-number": action[Output].(uint32),
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003317 "err": err})
David K. Bainbridge794735f2020-02-11 21:01:37 -08003318 return uint32(0), err
3319 }
Neha Sharma96b7bf22020-06-15 10:37:32 +00003320 logger.Infow(ctx, "input-nni-intfId-is", log.Fields{"intf-id": intfID})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303321 return intfID, nil
mgouda86543582025-10-29 20:58:16 +05303322 case voltha.Port_ETHERNET_UNI:
Sridhar Ravindrad104e8d2025-06-02 13:04:49 +05303323 if _, ok := action[Output]; ok {
3324 intfID, err := plt.IntfIDFromNniPortNum(ctx, action[Output].(uint32))
3325 if err != nil {
3326 logger.Debugw(ctx, "invalid-action-port-number",
3327 log.Fields{
3328 "port-number": action[Output].(uint32),
3329 "err": err})
3330 return uint32(0), nil
3331 }
3332 logger.Infow(ctx, "output-nni-intfId-is", log.Fields{"intf-id": intfID})
3333 return intfID, nil
3334 } else {
3335 logger.Debugw(ctx, "action-port-number-empty",
3336 log.Fields{
3337 "action": action})
3338 return uint32(0), nil
3339 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303340 }
3341 return uint32(0), nil
3342}
3343
3344// UpdateGemPortForPktIn updates gemport for packet-in in to the cache and to the kv store as well.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003345func (f *OpenOltFlowMgr) UpdateGemPortForPktIn(ctx context.Context, intfID uint32, onuID uint32, logicalPort uint32, gemPort uint32, pkt []byte) {
3346 cTag, priority, err := getCTagFromPacket(ctx, pkt)
3347 if err != nil {
3348 logger.Errorw(ctx, "unable-to-update-gem-port-for-packet-in",
3349 log.Fields{"intfID": intfID, "onuID": onuID, "logicalPort": logicalPort, "gemPort": gemPort, "err": err})
3350 return
3351 }
3352 pktInkey := rsrcMgr.PacketInInfoKey{IntfID: intfID, OnuID: onuID, LogicalPort: logicalPort, VlanID: cTag, Priority: priority}
Matteo Scandoloabf9c512020-06-23 19:31:14 -07003353
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003354 f.packetInGemPortLock.RLock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003355 lookupGemPort, ok := f.packetInGemPort[pktInkey]
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003356 f.packetInGemPortLock.RUnlock()
3357
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303358 if ok {
Matt Jeanneret1719a072019-12-20 14:50:14 -05003359 if lookupGemPort == gemPort {
Neha Sharma96b7bf22020-06-15 10:37:32 +00003360 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 +05303361 log.Fields{
3362 "pktinkey": pktInkey,
3363 "gem": gemPort})
Matt Jeanneret1719a072019-12-20 14:50:14 -05003364 return
3365 }
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303366 }
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003367 f.packetInGemPortLock.Lock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003368 f.packetInGemPort[pktInkey] = gemPort
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003369 f.packetInGemPortLock.Unlock()
Matt Jeanneret1719a072019-12-20 14:50:14 -05003370
npujarec5762e2020-01-01 14:08:48 +05303371 f.resourceMgr.UpdateGemPortForPktIn(ctx, pktInkey, gemPort)
Neha Sharma96b7bf22020-06-15 10:37:32 +00003372 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 +05303373 log.Fields{
3374 "pktinkey": pktInkey,
3375 "gem": gemPort})
Abhilash Laxmeshwarab0bd522019-10-21 15:05:15 +05303376}
3377
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003378// getCTagFromPacket retrieves and returns c-tag and priority value from a packet.
Esin Karaman7fb80c22020-07-16 14:23:33 +00003379func getCTagFromPacket(ctx context.Context, packet []byte) (uint16, uint8, error) {
mgouda86543582025-10-29 20:58:16 +05303380 if len(packet) < 18 {
Girish Kumara1ea2aa2020-08-19 18:14:22 +00003381 logger.Error(ctx, "unable-get-c-tag-from-the-packet--invalid-packet-length ")
Esin Karaman7fb80c22020-07-16 14:23:33 +00003382 return 0, 0, errors.New("invalid packet length")
3383 }
3384 outerEthType := (uint16(packet[12]) << 8) | uint16(packet[13])
3385 innerEthType := (uint16(packet[16]) << 8) | uint16(packet[17])
3386
3387 var index int8
3388 if outerEthType == 0x8100 {
3389 if innerEthType == 0x8100 {
3390 // q-in-q 802.1ad or 802.1q double tagged packet.
3391 // get the inner vlanId
3392 index = 18
3393 } else {
3394 index = 14
3395 }
3396 priority := (packet[index] >> 5) & 0x7
Akash Kankanala041a2122024-10-16 15:49:22 +05303397 // 13 bits composes vlanId value
Esin Karaman7fb80c22020-07-16 14:23:33 +00003398 vlan := ((uint16(packet[index]) << 8) & 0x0fff) | uint16(packet[index+1])
3399 return vlan, priority, nil
3400 }
3401 logger.Debugf(ctx, "No vlanId found in the packet. Returning zero as c-tag")
3402 return 0, 0, nil
3403}
3404
Joey Armstrong3f0e2422023-07-05 18:25:41 -04003405// clearMulticastFlowFromResourceManager removes a multicast flow from the KV store and
Girish Gowdra9602eb42020-09-09 15:50:39 -07003406// clears resources reserved for this multicast flow
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003407func (f *OpenOltFlowMgr) clearMulticastFlowFromResourceManager(ctx context.Context, flow *ofp.OfpFlowStats) error {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003408 removeFlowMessage := openoltpb2.Flow{FlowId: flow.Id, FlowType: Multicast}
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003409 logger.Debugw(ctx, "multicast-flow-to-be-deleted",
3410 log.Fields{
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003411 "flow": flow,
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003412 "flow-id": flow.Id,
3413 "device-id": f.deviceHandler.device.Id})
3414 // Remove from device
3415 if err := f.removeFlowFromDevice(ctx, &removeFlowMessage, flow.Id); err != nil {
3416 // DKB
3417 logger.Errorw(ctx, "failed-to-remove-multicast-flow",
3418 log.Fields{
3419 "flow-id": flow.Id,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003420 "err": err})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003421 return err
3422 }
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003423
3424 return nil
Esin Karamanccb714b2019-11-29 15:02:06 +00003425}
3426
khenaidoodc2116e2021-10-19 17:33:19 -04003427func (f *OpenOltFlowMgr) getTechProfileDownloadMessage(ctx context.Context, tpPath string, uniID uint32, onuDeviceID string) (*ia.TechProfileDownloadMessage, error) {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003428 tpInst, err := f.techprofile.GetTPInstance(ctx, tpPath)
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003429 if err != nil {
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003430 logger.Errorw(ctx, "error-fetching-tp-instance", log.Fields{"tpPath": tpPath})
khenaidoo106c61a2021-08-11 18:05:46 -04003431 return nil, err
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003432 }
3433
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003434 switch tpInst := tpInst.(type) {
3435 case *tp_pb.TechProfileInstance:
khenaidoo106c61a2021-08-11 18:05:46 -04003436 logger.Debugw(ctx, "fetched-tp-instance-successfully-formulating-tp-download-msg", log.Fields{"tpPath": tpPath})
khenaidoodc2116e2021-10-19 17:33:19 -04003437 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003438 DeviceId: onuDeviceID,
3439 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003440 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003441 TechTpInstance: &ia.TechProfileDownloadMessage_TpInstance{TpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003442 }, nil
khenaidoodc2116e2021-10-19 17:33:19 -04003443 case *tp_pb.EponTechProfileInstance:
3444 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003445 DeviceId: onuDeviceID,
3446 UniId: uniID,
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003447 TpInstancePath: tpPath,
khenaidoodc2116e2021-10-19 17:33:19 -04003448 TechTpInstance: &ia.TechProfileDownloadMessage_EponTpInstance{EponTpInstance: tpInst},
khenaidoo106c61a2021-08-11 18:05:46 -04003449 }, nil
Girish Gowdra8a0bdcd2021-05-13 12:31:04 -07003450 default:
3451 logger.Errorw(ctx, "unknown-tech", log.Fields{"tpPath": tpPath})
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003452 }
khenaidoodc2116e2021-10-19 17:33:19 -04003453 return &ia.TechProfileDownloadMessage{
khenaidoo106c61a2021-08-11 18:05:46 -04003454 DeviceId: onuDeviceID,
3455 UniId: uniID,
3456 TpInstancePath: tpPath,
3457 TechTpInstance: nil,
3458 }, nil
Girish Gowdraa09aeab2020-09-14 16:30:52 -07003459}
3460
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003461// revertTechProfileInstance is called when CreateScheduler or CreateQueues request fails
3462func (f *OpenOltFlowMgr) revertTechProfileInstance(ctx context.Context, sq schedQueue) {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003463 intfID := sq.intfID
3464 onuID := sq.onuID
3465 uniID := sq.uniID
3466 tpID := sq.tpID
3467
3468 var reverseDirection string
3469 if sq.direction == tp_pb.Direction_UPSTREAM {
3470 reverseDirection = "downstream"
3471 } else {
3472 reverseDirection = "upstream"
3473 }
3474
3475 // check reverse direction - if reverse meter exists, tech profile instance is in use - do not delete
yasin saplibddc2d72022-02-08 13:10:17 +00003476 if KvStoreMeter, _ := f.resourceMgr.GetMeterInfoForOnu(ctx, reverseDirection, onuID, uniID, tpID); KvStoreMeter != nil {
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003477 return
3478 }
3479
3480 // revert-delete tech-profile instance and delete tech profile id for onu
3481 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})
3482 uniPortName := getUniPortPath(f.deviceHandler.device.Id, intfID, int32(onuID), int32(uniID))
3483 _ = f.DeleteTechProfileInstance(ctx, intfID, onuID, uniID, uniPortName, tpID)
yasin saplibddc2d72022-02-08 13:10:17 +00003484 _ = f.resourceMgr.RemoveTechProfileIDForOnu(ctx, onuID, uniID, tpID)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003485
3486 // free gem/alloc
3487 switch techprofileInst := sq.tpInst.(type) {
3488 case *tp_pb.TechProfileInstance:
3489 for _, gem := range techprofileInst.UpstreamGemPortAttributeList {
yasin saplibddc2d72022-02-08 13:10:17 +00003490 f.resourceMgr.FreeGemPortID(ctx, onuID, uniID, gem.GemportId)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003491 }
yasin saplibddc2d72022-02-08 13:10:17 +00003492 f.resourceMgr.FreeAllocID(ctx, onuID, uniID, techprofileInst.UsScheduler.AllocId, true)
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003493 }
3494}
3495
3496// revertSchduler is called when CreateQueues request fails
3497func (f *OpenOltFlowMgr) revertScheduler(ctx context.Context, sq schedQueue, TrafficSched []*tp_pb.TrafficScheduler) {
3498 // revert scheduler
3499 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 +05303500 subCtx, cancel := context.WithTimeout(log.WithSpanFromContext(context.Background(), ctx), f.deviceHandler.cfg.RPCTimeout)
3501 _, _ = f.deviceHandler.Client.RemoveTrafficSchedulers(subCtx, &tp_pb.TrafficSchedulers{
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003502 IntfId: sq.intfID, OnuId: sq.onuID,
3503 UniId: sq.uniID, PortNo: sq.uniPort,
3504 TrafficScheds: TrafficSched})
bseenivaa1622112025-12-11 18:24:02 +05303505 cancel()
Gamze Abaka411ef2f2021-11-22 08:38:08 +00003506}
Girish Gowdra6071f382021-12-14 12:52:04 +05303507
3508// validateMeter validates if there is a meter mismatch for the given direction. It also clears the stale meter if the reference count is zero
3509func (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 +00003510 meterInfo, err := f.resourceMgr.GetMeterInfoForOnu(ctx, direction, onuID, uniID, tpID)
Girish Gowdra6071f382021-12-14 12:52:04 +05303511 if err != nil {
3512 return olterrors.NewErrNotFound("meter",
3513 log.Fields{"intf-id": intfID,
3514 "onu-id": onuID,
3515 "uni-id": uniID,
3516 "device-id": f.deviceHandler.device.Id}, err)
3517 }
3518
3519 if meterInfo != nil {
3520 // If RefCnt become 0 clear the meter information from the DB.
3521 if meterInfo.MeterID != meterID && meterInfo.RefCnt == 0 {
yasin saplibddc2d72022-02-08 13:10:17 +00003522 if err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, onuID, uniID, tpID); err != nil {
Girish Gowdra6071f382021-12-14 12:52:04 +05303523 return err
3524 }
3525 } else if meterInfo.MeterID != meterID {
3526 logger.Errorw(ctx, "meter-mismatch-for-direction",
3527 log.Fields{"direction": direction,
3528 "kv-store-meter-id": meterInfo.MeterID,
3529 "meter-id-in-flow": meterID,
3530 "device-id": f.deviceHandler.device.Id})
3531 return olterrors.NewErrInvalidValue(log.Fields{
3532 "unsupported": "meter-id",
3533 "kv-store-meter-id": meterInfo.MeterID,
3534 "meter-id-in-flow": meterID,
3535 "device-id": f.deviceHandler.device.Id}, nil)
3536 }
3537 }
3538 return nil
3539}
Girish Gowdraf3728b12022-02-02 21:46:51 -08003540
3541func (f *OpenOltFlowMgr) removeMeterReference(ctx context.Context, direction string, sq schedQueue) error {
3542 /* After we successfully remove the scheduler configuration on the OLT device,
3543 * delete the meter id on the KV store.
3544 */
yasin saplibddc2d72022-02-08 13:10:17 +00003545 err := f.resourceMgr.RemoveMeterInfoForOnu(ctx, direction, sq.onuID, sq.uniID, sq.tpID)
Girish Gowdraf3728b12022-02-02 21:46:51 -08003546 if err != nil {
3547 return olterrors.NewErrAdapter("unable-to-remove-meter",
3548 log.Fields{
3549 "onu": sq.onuID,
3550 "device-id": f.deviceHandler.device.Id,
3551 "intf-id": sq.intfID,
3552 "onu-id": sq.onuID,
3553 "uni-id": sq.uniID,
3554 "uni-port": sq.uniPort}, err)
3555 }
3556 logger.Debugw(ctx, "removed-meter-from-KV-store-successfully",
3557 log.Fields{
3558 "dir": direction,
3559 "device-id": f.deviceHandler.device.Id,
3560 "intf-id": sq.intfID,
3561 "onu-id": sq.onuID,
3562 "uni-id": sq.uniID,
3563 "uni-port": sq.uniPort})
3564 return err
3565}